Commit afa68ed2e0 for openssl.org
commit afa68ed2e00d560f4c71a5e7a8ef2046b49bdd83
Author: Dr. David von Oheimb <David.von.Oheimb@siemens.com>
Date: Fri Jul 29 11:32:50 2022 +0200
PKCS7 and SMIME: improve documentation w.r.t. untrusted and signer certificates
Reviewed-by: Mounir Idrassi <mounir.idrassi@idrix.fr>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
Merge-date: Thu Sep 3 09:26:56 2026
Merged-from: https://github.com/openssl/openssl/pull/22285
diff --git a/apps/cms.c b/apps/cms.c
index fff3b2fbea..ee59b9faa0 100644
--- a/apps/cms.c
+++ b/apps/cms.c
@@ -226,8 +226,8 @@ const OPTIONS cms_options[] = {
OPT_R_OPTIONS,
OPT_SECTION("Encryption and decryption"),
- { "originator", OPT_ORIGINATOR, 's', "Originator certificate file" },
- { "recip", OPT_RECIP, '<', "Recipient cert file" },
+ { "originator", OPT_ORIGINATOR, 's', "Originator certificate" },
+ { "recip", OPT_RECIP, '<', "Recipient cert" },
{ "cert...", OPT_PARAM, '.',
"Recipient certs (optional; used only when encrypting)" },
{ "", OPT_CIPHER, '-',
@@ -247,7 +247,7 @@ const OPTIONS cms_options[] = {
OPT_SECTION("Signing"),
{ "md", OPT_MD, 's', "Digest algorithm to use" },
- { "signer", OPT_SIGNER, 's', "Signer certificate input file" },
+ { "signer", OPT_SIGNER, 's', "Signer certificate input" },
{ "certfile", OPT_CERTFILE, '<',
"Extra signer and intermediate CA certificates to include when signing" },
{ OPT_MORE_STR, 0, 0,
@@ -514,6 +514,10 @@ int cms_main(int argc, char **argv)
break;
case OPT_NOCERTS:
flags |= CMS_NOCERTS;
+ /*
+ * Note that this does not affect certificates in variable 'other'
+ * containing extra certs loaded according to the -certfile option.
+ */
break;
case OPT_NOATTR:
flags |= CMS_NOATTR;
@@ -982,7 +986,7 @@ int cms_main(int argc, char **argv)
for (; *argv != NULL; argv++) {
cert = load_cert(*argv, FORMAT_UNDEF,
- "recipient certificate file");
+ "recipient certificate");
if (cert == NULL)
goto end;
if (!sk_X509_push(encerts, cert))
@@ -992,7 +996,7 @@ int cms_main(int argc, char **argv)
}
if (certfile != NULL
- && !load_certs(certfile, 0, &other, NULL, "certificate file"))
+ && !load_certs(certfile, 0, &other, NULL, "extra certificates"))
goto end;
if (recipfile != NULL && (operation == SMIME_DECRYPT)
diff --git a/apps/smime.c b/apps/smime.c
index 7f639ebd5b..fd817ca98b 100644
--- a/apps/smime.c
+++ b/apps/smime.c
@@ -117,7 +117,7 @@ const OPTIONS smime_options[] = {
{ "nodetach", OPT_NODETACH, '-', "Use opaque signing" },
{ "noattr", OPT_NOATTR, '-', "Don't include any signed attributes" },
{ "binary", OPT_BINARY, '-', "Don't translate message to text" },
- { "signer", OPT_SIGNER, 's', "Signer certificate file" },
+ { "signer", OPT_SIGNER, 's', "Signer certificate" },
{ "content", OPT_CONTENT, '<',
"Supply or override content for detached signature" },
{ "nocerts", OPT_NOCERTS, '-',
@@ -127,11 +127,7 @@ const OPTIONS smime_options[] = {
{ "nosigs", OPT_NOSIGS, '-', "Don't verify message signature" },
{ "noverify", OPT_NOVERIFY, '-', "Don't verify signers certificate" },
- { "certfile", OPT_CERTFILE, '<',
- "Extra signer and intermediate CA certificates to include when signing" },
- { OPT_MORE_STR, 0, 0,
- "or to use as preferred signer certs and for chain building when verifying" },
- { "recip", OPT_RECIP, '<', "Recipient certificate file for decryption" },
+ { "recip", OPT_RECIP, '<', "Recipient certificate for decryption" },
OPT_SECTION("Email"),
{ "to", OPT_TO, 's', "To address" },
@@ -141,6 +137,10 @@ const OPTIONS smime_options[] = {
{ "nosmimecap", OPT_NOSMIMECAP, '-', "Omit the SMIMECapabilities attribute" },
OPT_SECTION("Certificate chain"),
+ { "certfile", OPT_CERTFILE, '<',
+ "Extra signer and intermediate CA certificates to include when signing" },
+ { OPT_MORE_STR, 0, 0,
+ "or to use as preferred signer certs and for chain building when verifying" },
{ "CAfile", OPT_CAFILE, '<', "File in PEM format with trusted CA certs" },
{ "CApath", OPT_CAPATH, '/', "Dir with trusted CA cert files in PEM format" },
{ "CAstore", OPT_CASTORE, ':', "URI of store with trusted CA certs" },
@@ -151,8 +151,8 @@ const OPTIONS smime_options[] = {
{ "no-CAstore", OPT_NOCASTORE, '-',
"Do not load certificates from the default certificates store" },
{ "nochain", OPT_NOCHAIN, '-',
- "set PKCS7_NOCHAIN so certificates contained in the message are not used as untrusted CAs" },
- { "crlfeol", OPT_CRLFEOL, '-', "Use CRLF as EOL termination instead of LF only" },
+ "Do not use certs contained in the message as untrusted CAs for chain building" },
+ { "crlfeol", OPT_CRLFEOL, '-', "Use CRLF as EOL termination (instead of LF only)" },
OPT_R_OPTIONS,
OPT_V_OPTIONS,
@@ -520,7 +520,7 @@ int smime_main(int argc, char **argv)
}
if (certfile != NULL) {
- if (!load_certs(certfile, 0, &other, NULL, "certificates")) {
+ if (!load_certs(certfile, 0, &other, NULL, "extra certificates")) {
ERR_print_errors(bio_err);
goto end;
}
@@ -624,7 +624,7 @@ int smime_main(int argc, char **argv)
p7 = PKCS7_sign_ex(NULL, NULL, other, in, flags, libctx, app_get0_propq());
if (p7 == NULL)
goto end;
- if (flags & PKCS7_NOCERTS) {
+ if ((flags & PKCS7_NOCERTS) != 0) { /* still add list given via -certfile */
for (i = 0; i < sk_X509_num(other); i++) {
X509 *x = sk_X509_value(other, i);
PKCS7_add_certificate(p7, x);
diff --git a/crypto/cms/cms_local.h b/crypto/cms/cms_local.h
index df2b398d61..0b1f54834f 100644
--- a/crypto/cms/cms_local.h
+++ b/crypto/cms/cms_local.h
@@ -84,6 +84,7 @@ struct CMS_SignedData_st {
int32_t version;
STACK_OF(X509_ALGOR) *digestAlgorithms;
CMS_EncapsulatedContentInfo *encapContentInfo;
+ /* untrusted certificates for chain building, may include signer certs: */
STACK_OF(CMS_CertificateChoices) *certificates;
STACK_OF(CMS_RevocationInfoChoice) *crls;
STACK_OF(CMS_SignerInfo) *signerInfos;
diff --git a/crypto/cms/cms_sd.c b/crypto/cms/cms_sd.c
index 8d1bf722cc..87dbd32553 100644
--- a/crypto/cms/cms_sd.c
+++ b/crypto/cms/cms_sd.c
@@ -729,7 +729,6 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
}
if (!(flags & CMS_NOCERTS)) {
- /* NB ignore -1 return for duplicate cert */
if (!CMS_add1_cert(cms, signer)) {
ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB);
goto err;
@@ -908,6 +907,7 @@ int CMS_set1_signers_certs(CMS_ContentInfo *cms, const STACK_OF(X509) *scerts,
if (si->signer != NULL)
continue;
+ /* If any certificates passed they take priority */
for (j = 0; j < sk_X509_num(scerts); j++) {
x = sk_X509_value(scerts, j);
if (CMS_SignerInfo_cert_cmp(si, x) == 0) {
diff --git a/doc/man1/openssl-cms.pod.in b/doc/man1/openssl-cms.pod.in
index 266d4782c4..ef2fc45988 100644
--- a/doc/man1/openssl-cms.pod.in
+++ b/doc/man1/openssl-cms.pod.in
@@ -64,8 +64,8 @@ Keys and password options:
Encryption options:
-[B<-originator> I<file>]
-[B<-recip> I<file>]
+[B<-originator> I<filename>|I<uri>]
+[B<-recip> I<filename>|I<uri>]
[I<recipient-cert> ...]
[B<-I<cipher>>]
[B<-kekcipher> I<cipher>]
@@ -81,8 +81,8 @@ Encryption options:
Signing options:
[B<-md> I<digest>]
-[B<-signer> I<file>]
-[B<-certfile> I<file>]
+[B<-signer> I<filename>|I<uri>]
+[B<-certfile> I<filename>|I<uri>]
[B<-cades>]
[B<-nodetach>]
[B<-nocerts>]
@@ -360,8 +360,8 @@ B<KEKRecipientInfo> structures.
The private key to use when signing or decrypting. This must match the
corresponding certificate. If this option is not specified then the
-private key must be included in the certificate file specified with
-the B<-recip> or B<-signer> file. When signing this option can be used
+private key must be included in the certificate specified with
+the B<-recip> or B<-signer> option. When signing this option can be used
multiple times to specify successive keys.
=item B<-passin> I<arg>
@@ -391,13 +391,13 @@ See L<openssl-format-options(1)> for details.
=over 4
-=item B<-originator> I<file>
+=item B<-originator> I<filename>|I<uri>
A certificate of the originator of the encrypted message. Necessary for
decryption when Key Agreement is in use for a shared key. Currently, not
allowed for encryption.
-=item B<-recip> I<file>
+=item B<-recip> I<filename>|I<uri>
When decrypting a message this specifies the certificate of the recipient.
The certificate must match one of the recipients of the message.
@@ -412,7 +412,7 @@ option.
=item I<recipient-cert> ...
This is an alternative to using the B<-recip> option when encrypting a message.
-One or more certificate filenames may be given.
+One or more certificates may be given.
=item B<-I<cipher>>
@@ -481,16 +481,25 @@ and a digest algorithm required by the signing scheme will be used. This is
the case for EdDSA (RFC 8419). For SLH-DSA (RFC 9814) and ML-DSA (RFC 9882),
the scheme-suggested digest algorithm will only be used if none is given.
-=item B<-signer> I<file>
+=item B<-signer> I<filename>|I<uri>
-A signing certificate. When signing or resigning a message, this option can be
+A signer certificate. When signing or resigning a message, this option can be
used multiple times if more than one signer is required.
-=item B<-certfile> I<file>
+=item B<-certfile> I<filename>|I<uri>
+
+Provide extra certificates.
+When signing, these will be included with the message and can serve
+both as candidate untrusted CA certificates for chain building in verification
+and as fallback signer certificates.
+When verifying, the provided certificates will be used for chain building
+and take precedence over the signer certificates in the message
+as a source of candidate signers.
+With B<-nointern> these will be the only signer certificates considered.
-Allows additional certificates to be specified. When signing these will
-be included with the message. When verifying, these will be searched for
-signer certificates and will be used for chain building.
+Note that a message can have multiple signers.
+When verifying a multi-signed message, all the signatures must be valid,
+and so all the signer certificates need to be available.
The input can be in PEM, DER, or PKCS#12 format.
@@ -510,9 +519,10 @@ the MIME type multipart/signed is used.
=item B<-nocerts>
-When signing a message the signer's certificate is normally included
-with this option it is excluded. This will reduce the size of the
-signed message but the verifier must have a copy of the signers certificate
+When signing a message, the signer certificates are normally included,
+but this option disables their inclusion.
+This will reduce the size of the signed message,
+but the verifier must then have a copy of those certificates
available locally (passed using the B<-certfile> option for example).
=item B<-noattr>
@@ -555,8 +565,8 @@ option B<must> but supplied if a signed receipt is requested.
=item B<-signer> I<file>
-If a message has been verified successfully then the signers certificate(s)
-will be written to this file if the verification was successful.
+If a message has been verified successfully, then the signer certificate(s)
+will be written to this file.
=item B<-content> I<filename>
@@ -584,10 +594,11 @@ Do not verify the signers certificate of a signed message.
=item B<-nointern>
-When verifying a message normally certificates (if any) included in
-the message are searched for the signing certificate. With this option
-only the certificates specified in the B<-certfile> option are used.
-The supplied certificates can still be used as untrusted CAs however.
+Normally, when verifying a message, the certificates (if any) included in
+the message are searched for the signer certificates. With this option,
+only the certificates given with the B<-certfile> option are used.
+However, the certificates included in the message are still used
+as candidate intermediate CA certificates during chain construction.
=item B<-cades>
diff --git a/doc/man1/openssl-smime.pod.in b/doc/man1/openssl-smime.pod.in
index 498d0c5725..7fd9200bbf 100644
--- a/doc/man1/openssl-smime.pod.in
+++ b/doc/man1/openssl-smime.pod.in
@@ -19,8 +19,8 @@ B<openssl> B<smime>
[B<-crlfeol>]
[B<-I<cipher>>]
[B<-in> I<file>]
-[B<-certfile> I<file>]
-[B<-signer> I<file>]
+[B<-certfile> I<filename>|I<uri>]
+[B<-signer> I<filename>|I<uri>]
[B<-nointern>]
[B<-noverify>]
[B<-nochain>]
@@ -29,7 +29,7 @@ B<openssl> B<smime>
[B<-noattr>]
[B<-nodetach>]
[B<-nosmimecap>]
-[B<-recip> I< file>]
+[B<-recip> I<filename>|I<uri>]
[B<-inform> B<DER>|B<PEM>|B<SMIME>]
[B<-outform> B<DER>|B<PEM>|B<SMIME>]
[B<-keyform> B<DER>|B<PEM>|B<P12>]
@@ -100,6 +100,10 @@ Resign a message: take an existing message and one or more new signers.
Verify signed mail. Expects a signed mail message on input and outputs
the signed data. Both clear text and opaque signing is supported.
+Unless B<-nochain> is specified, validation of signer certificates and their
+chain is done by default w.r.t. the S/MIME signing (C<smimesign>) purpose.
+For details see L<openssl-verification-options(1)/Certificate Extensions>.
+
=item B<-pk7out>
Takes an input message and writes out a PEM encoded PKCS#7 structure.
@@ -178,10 +182,12 @@ If not specified, AES-256-CBC is used as the default. Only used with B<-encrypt>
=item B<-nointern>
-When verifying a message normally certificates (if any) included in
-the message are searched for the signing certificate. With this option
-only the certificates specified in the B<-certfile> option are used.
-The supplied certificates can still be used as untrusted CAs however.
+Normally, when verifying a message, the certificates (if any) included in
+the message are searched for the signer certificates. With this option,
+only the certificates given with the B<-certfile> option are used.
+However, the certificates included in the message are still used
+as candidate intermediate CA certificates during chain construction
+unless B<-nochain> is also specified.
=item B<-noverify>
@@ -189,8 +195,10 @@ Do not verify the signers certificate of a signed message.
=item B<-nochain>
-Do not do chain verification of signers certificates; that is, do not
-use the certificates in the signed message as untrusted CAs.
+When verifying the signer certificates of a signed message, do not use the
+certificates in the message as candidate CA certificates for chain building.
+This also disables the default use of the S/MIME signing (C<smimesign>) purpose.
+To re-enable it, B<-purpose smimesign> can be specified.
=item B<-nosigs>
@@ -198,11 +206,19 @@ Don't try to verify the signatures on the message.
=item B<-nocerts>
-When signing a message, the signer's certificate is normally included.
-With this option it is excluded. This will reduce the size of the
-signed message, but the verifier must have a copy of the signers certificate
+When signing a message, the signer certificates are normally included,
+but this option disables their inclusion.
+This will reduce the size of the signed message,
+but the verifier must have a copy of those certificates
available locally (passed using the B<-certfile> option for example).
+With the -sign operation,
+setting this option has special effect on any extra certificates supplied via the
+B<-certfile> option: while signer certificates supplied via the B<-signer> option are
+not included, the extra certificates from B<-certfile> are included in the given order.
+This can be used to specify the order certificates appear in the PKCS#7 structure
+as a workaround for broken applications that require a certain ordering.
+
=item B<-noattr>
Normally, when a message is signed, a set of attributes are included which
@@ -232,22 +248,32 @@ is useful when handling binary data which may not be in MIME format.
Normally the output file uses a single B<LF> as end of line. When this
option is present B<CRLF> is used instead.
-=item B<-certfile> I<file>
+=item B<-certfile> I<filename>|I<uri>
+
+Provide extra certificates.
+When signing, these will be included with the message and can serve
+both as candidate untrusted CA certificates for chain building in verification
+and as fallback signer certificates.
+When verifying, the provided certificates will be used for chain building
+and take precedence over the signer certificates in the message
+as a source of candidate signers.
+With B<-nointern> these will be the only signer certificates considered.
-Allows additional certificates to be specified. When signing these will
-be included with the message. When verifying, these will be searched for
-signer certificates and will be used for chain building.
+Note that a message can have multiple signers.
+When verifying a multi-signed message, all the signatures must be valid,
+and so all the signer certificates need to be available.
The input can be in PEM, DER, or PKCS#12 format.
-=item B<-signer> I<file>
+=item B<-signer> I<filename>|I<uri>
-A signing certificate when signing or resigning a message, this option can be
-used multiple times if more than one signer is required. If a message is being
-verified then the signers certificates will be written to this file if the
-verification was successful.
+A signer certificate. When signing or resigning a message, this option can be
+used multiple times if more than one signer is required.
+If a message has been verified successfully, then the signer certificate(s)
+will be written to this file.
+In the verification case, the option argument format I<uri> cannot be used.
-=item B<-recip> I<file>
+=item B<-recip> I<filename>|I<uri>
The recipients certificate when decrypting a message. This certificate
must match one of the recipients of the message or an error occurs.
@@ -257,7 +283,7 @@ must match one of the recipients of the message or an error occurs.
The private key to use when signing or decrypting. This must match the
corresponding certificate. If this option is not specified then the
private key must be included in the certificate file specified with
-the B<-recip> or B<-signer> file. When signing this option can be used
+the B<-recip> or B<-signer> option. When signing this option can be used
multiple times to specify successive keys.
=item B<-passin> I<arg>
@@ -456,7 +482,7 @@ algorithms as supplied in the SMIMECapabilities signed attribute. This means the
user has to manually include the correct encryption algorithm. It should store
the list of permitted ciphers in a database and only use those.
-No revocation checking is done on the signer's certificate.
+No revocation checking is done on signer certificates.
The current code can only handle S/MIME v2 messages, the more complex S/MIME v3
structures may cause parsing errors.
diff --git a/doc/man3/CMS_add0_cert.pod b/doc/man3/CMS_add0_cert.pod
index 8f7e0e9e42..ae0f28617d 100644
--- a/doc/man3/CMS_add0_cert.pod
+++ b/doc/man3/CMS_add0_cert.pod
@@ -22,22 +22,23 @@ CMS_add0_crl, CMS_add1_crl, CMS_get1_crls
CMS_add0_cert() and CMS_add1_cert() add certificate I<cert> to I<cms>
unless it is already present.
-This is used by L<CMS_sign_ex(3)> and L<CMS_sign(3)> and may be used before
-calling L<CMS_verify(3)> to help chain building in certificate validation.
+Signer certificates and intermediate CA certificates are usually added
+to a CMS structure by L<CMS_sign_ex(3)> and L<CMS_sign(3)>, yet further
+such certificates may be added in advance by directly calling these functions.
+The verifier of the message can use the included certificates
+as candidate signer certificates and for chain building.
+These functions may also be used before calling L<CMS_verify(3)> to add
+fallback signer certificates or intermediate CA certificates for chain building.
As the 0 implies, CMS_add0_cert() adds I<cert> internally to I<cms>
and on success it must not be freed up by the caller.
In contrast, the caller of CMS_add1_cert() must free I<cert>.
I<cms> must be of type signed data or (authenticated) enveloped data.
-For signed data, such a certificate can be used when signing or verifying
-to fill in the signer certificate or to provide an extra CA certificate
-that may be needed for chain building in certificate validation.
CMS_get1_certs() returns all certificates in I<cms>.
CMS_add0_crl() and CMS_add1_crl() add CRL I<crl> to I<cms>.
I<cms> must be of type signed data or (authenticated) enveloped data.
-For signed data, such a CRL may be used in certificate validation
-with L<CMS_verify(3)>.
+Such a CRL may be used in certificate validation, e.g., with L<CMS_verify(3)>.
It may be given both for inclusion when signing a CMS message
and when verifying a signed CMS message.
diff --git a/doc/man3/CMS_verify.pod b/doc/man3/CMS_verify.pod
index 89f6f01311..303b864eca 100644
--- a/doc/man3/CMS_verify.pod
+++ b/doc/man3/CMS_verify.pod
@@ -32,8 +32,9 @@ CMS_SignerInfo_verify_content, CMS_SignerInfo_verify_ex
CMS_verify() is very similar to L<PKCS7_verify(3)>. It verifies a
B<CMS SignedData> structure contained in a structure of type B<CMS_ContentInfo>.
I<cms> points to the B<CMS_ContentInfo> structure to verify.
-The optional I<certs> parameter refers to a set of certificates
-in which to search for signing certificates.
+The optional I<certs> parameter can provide a list of certificates
+that are used for searching for signer certificates first,
+as far as they are not already associated with the B<CMS_SignerInfo>.
It is also used
as a source of untrusted intermediate CA certificates for chain building.
I<cms> may contain extra untrusted CA certificates that may be used for
@@ -57,7 +58,7 @@ Also the list of CRLs must not contain duplicates.
The optional parameters library context I<libctx> and property query I<propq>
are used when retrieving algorithms from providers.
-CMS_get0_signers() retrieves the signing certificate(s) from I<cms>; it may only
+CMS_get0_signers() retrieves the signer certificate(s) from I<cms>; it may only
be called after a successful CMS_verify() or CMS_SignedData_verify() operation.
CMS_SignerInfo_verify() verifies the signed attributes attached to the given
@@ -83,15 +84,18 @@ Initially some sanity checks are performed on I<cms>. The type of I<cms> must
be SignedData. There must be at least one signature on the data and if
the content is detached I<detached_data> cannot be NULL.
-An attempt is made to locate all the signing certificate(s), first looking in
-the I<certs> parameter (if it is not NULL) and then looking in any
-certificates contained in the I<cms> structure unless B<CMS_NOINTERN> is set.
-If any signing certificate cannot be located the operation fails unless
-B<CMS_VERIFY_PARTIAL> is set, where one signing certificate can be sufficient.
-
-Each found signing certificate is chain verified
-using I<store> as the trusted certificate store if supplied,
-and by default requiring the I<smimesign> purpose.
+An attempt is made to locate all the signer certificate(s)
+as far as they are not already associated with the B<CMS_SignerInfo>.
+First, they are searched among the certificates provided
+in the I<certs> parameter (if it is not NULL).
+Then they are looked up among the certificates contained
+in the I<cms> structure unless B<CMS_NOINTERN> is set.
+If any signer certificate cannot be located, the operation fails unless
+B<CMS_VERIFY_PARTIAL> is set, where one signer certificate can be sufficient.
+Signer associations are retained between verification calls.
+
+Each found signer certificate is chain verified using I<store> as the trusted
+certificate store if supplied, and by default requiring the I<smimesign> purpose.
The default purpose may be overridden using L<X509_STORE_set_purpose(3)>.
Any internal certificates in the message, which may have been added using
L<CMS_add1_cert(3)>, are used as untrusted CAs.
@@ -113,8 +117,9 @@ Any of the following flags (ored together) can be passed in the I<flags>
parameter to change the default verify behaviour.
If B<CMS_NOINTERN> is set the certificates in the message itself are not
-searched when locating the signing certificate(s).
-This means that all the signing certificates must be in the I<certs> parameter.
+searched when locating the signer certificate(s).
+This means that the signer certificates that are not already associated
+with the B<CMS_SignerInfo> must be in the I<certs> parameter.
If B<CMS_NOCRL> is set and CRL checking is enabled in I<store> then any
CRLs in the message itself and provided via the I<crls> parameter are ignored.
@@ -123,7 +128,7 @@ If the B<CMS_TEXT> flag is set MIME headers for type C<text/plain> are deleted
from the content. If the content is not of type C<text/plain> then an error is
returned.
-If B<CMS_NO_SIGNER_CERT_VERIFY> is set the signing certificates are not
+If B<CMS_NO_SIGNER_CERT_VERIFY> is set the signer certificates are not
chain verified, unless B<CMS_CADES> flag is also set.
If B<CMS_NO_ATTR_VERIFY> is set the signed attributes signature is not
@@ -137,7 +142,8 @@ If B<CMS_NO_CONTENT_VERIFY> is set then the content digest is not checked.
=head1 NOTES
-One application of B<CMS_NOINTERN> is to only accept messages signed by
+As far as signer certificates are not already associated with B<CMS_SignerInfo>,
+one application of B<CMS_NOINTERN> can be to only accept messages signed by
a small number of certificates. The acceptable certificates would be passed
in the I<certs> parameter. In this case if the signer certificate is not one
of the certificates supplied in I<certs> then the verify will fail because the
@@ -173,7 +179,7 @@ The error can be obtained from L<ERR_get_error(3)>.
=head1 BUGS
-The trusted certificate store is not searched for the signing certificate.
+The trusted certificate store is not searched for the signer certificate.
This is primarily due to the inadequacies of the current B<X509_STORE>
functionality.
diff --git a/doc/man3/PKCS7_sign.pod b/doc/man3/PKCS7_sign.pod
index 620b3b699d..7670cb300e 100644
--- a/doc/man3/PKCS7_sign.pod
+++ b/doc/man3/PKCS7_sign.pod
@@ -20,8 +20,9 @@ PKCS7_sign_ex, PKCS7_sign
PKCS7_sign_ex() creates and returns a PKCS#7 signedData structure.
I<signcert> is the certificate to sign with, I<pkey> is the corresponding
-private key. I<certs> is an optional set of extra certificates to include
-in the PKCS#7 structure (for example any intermediate CAs in the chain).
+private key. I<certs> is an optional additional set of certificates to include,
+unless B<PKCS7_NOCERTS> is set, in the B<PKCS7> structure. They may be used as
+untrusted CA certificates for chain building or as extra signer certificates.
The library context I<libctx> and property query I<propq> are used when
retrieving algorithms from providers.
@@ -36,14 +37,14 @@ Many S/MIME clients expect the signed content to include valid MIME headers. If
the B<PKCS7_TEXT> flag is set MIME headers for type C<text/plain> are prepended
to the data.
-If B<PKCS7_NOCERTS> is set the signer's certificate and the extra I<certs>
-will not be included in the PKCS7 structure.
-The signer's certificate must still be supplied in the I<signcert> parameter
-though. This can reduce the size of the signatures if the signer's certificates
+If B<PKCS7_NOCERTS> is set, the signer's certificate and extra certificates
+given in the I<certs> parameter will not be included in the B<PKCS7> structure.
+The signer's certificate must still be supplied in the B<signcert> parameter
+though. This can reduce the size of the signatures if the signer certificates
can be obtained by other means: for example a previously signed message.
-The data being signed is included in the PKCS7 structure, unless
-B<PKCS7_DETACHED> is set in which case it is omitted. This is used for PKCS7
+The data being signed is included in the B<PKCS7> structure, unless
+B<PKCS7_DETACHED> is set in which case it is omitted. This is used for PKCS#7
detached signatures which are used in S/MIME plaintext signed messages for
example.
@@ -90,7 +91,7 @@ called to finalize the structure if streaming is not enabled. Alternative
signing digests can also be specified using this method.
If I<signcert> and I<pkey> are NULL then a certificates only
-PKCS#7 structure is output.
+B<PKCS7> structure is output.
In versions of OpenSSL before 1.0.0 the I<signcert> and I<pkey> parameters must
not be NULL.
@@ -105,7 +106,7 @@ Some advanced attributes such as counter signatures are not supported.
=head1 RETURN VALUES
-PKCS7_sign_ex() and PKCS7_sign() return either a valid PKCS7 structure
+PKCS7_sign_ex() and PKCS7_sign() return either a valid B<PKCS7> structure
or NULL if an error occurred. The error can be obtained from ERR_get_error(3).
=head1 SEE ALSO
diff --git a/doc/man3/PKCS7_sign_add_signer.pod b/doc/man3/PKCS7_sign_add_signer.pod
index 24353484ab..b484cd9dc0 100644
--- a/doc/man3/PKCS7_sign_add_signer.pod
+++ b/doc/man3/PKCS7_sign_add_signer.pod
@@ -30,16 +30,31 @@ Unless the B<PKCS7_REUSE_DIGEST> flag is set the returned B<PKCS7> structure
is not complete and must be finalized either by streaming (if applicable) or
a call to PKCS7_final().
+PKCS7_add_certificate() adds to the B<PKCS7> structure I<p7> the certificate
+I<cert>, which may be an end-entity (signer) certificate
+or a CA certificate useful for chain building.
+This is done internally by L<PKCS7_sign_ex(3)> and similar signing functions
+but can also be called directly to add another such certificate.
+It may be used also before calling L<PKCS7_verify(3)>
+to provide any missing certificate(s) needed for chain building
+or to provide a fallback signer certificate.
+
+PKCS7_add_crl() adds the CRL I<crl> to the B<PKCS7> structure I<p7>.
+This may be called to provide certificate status information
+to be included when signing or to use when verifying the B<PKCS7> structure.
=head1 NOTES
-The main purpose of this function is to provide finer control over a PKCS#7
+The main purpose of these functions is to provide finer control over a PKCS#7
signed data structure where the simpler PKCS7_sign() function defaults are
not appropriate. For example if multiple signers or non default digest
algorithms are needed.
+The PKCS7 structure I<p7> argument must be of type signed data or
+signed-and-enveloped data or an error will be returned.
+
Any of the following flags (ored together) can be passed in the I<flags>
-parameter.
+parameter of PKCS7_sign_add_signer().
If B<PKCS7_REUSE_DIGEST> is set then an attempt is made to copy the content
digest value from the B<PKCS7> structure: to add a signer to an existing structure.
@@ -47,15 +62,15 @@ An error occurs if a matching digest value cannot be found to copy. The
returned B<PKCS7> structure will be valid and finalized when this flag is set.
If B<PKCS7_PARTIAL> is set in addition to B<PKCS7_REUSE_DIGEST> then the
-B<PKCS7_SIGNER_INO> structure will not be finalized so additional attributes
+B<PKCS7_SIGNER_INFO> structure will not be finalized so additional attributes
can be added. In this case an explicit call to PKCS7_SIGNER_INFO_sign() is
needed to finalize it.
-If B<PKCS7_NOCERTS> is set the signer's certificate will not be included in the
-B<PKCS7> structure, the signer's certificate must still be supplied in the
-I<signcert> parameter though. This can reduce the size of the signature if the
-signers certificate can be obtained by other means: for example a previously
-signed message.
+If B<PKCS7_NOCERTS> is set, this call does not add I<signcert> to the
+B<PKCS7> structure. Certificates already present in the structure are left
+unchanged. I<signcert> must still be supplied. This can reduce the size of
+the signature if the signer certificate can be obtained by other means,
+for example a previously signed message.
The signedData structure includes several PKCS#7 authenticatedAttributes
including the signing time, the PKCS#7 content type and the supported list of
@@ -67,25 +82,14 @@ If present the SMIMECapabilities attribute indicates support for the following
algorithms: triple DES, 128 bit RC2, 64 bit RC2, DES and 40 bit RC2. If any of
these algorithms is disabled then it will not be included.
-PKCS7_sign_add_signers() returns an internal pointer to the B<PKCS7_SIGNER_INFO>
-structure just added, which can be used to set additional attributes
-before it is finalized.
-
-PKCS7_add_certificate() adds to the B<PKCS7> structure I<p7> the certificate
-I<cert>, which may be an end-entity (signer) certificate
-or a CA certificate useful for chain building.
-This is done internally by L<PKCS7_sign_ex(3)> and similar signing functions.
-It may have to be used before calling L<PKCS7_verify(3)>
-in order to provide any missing certificate(s) needed for verification.
-
-PKCS7_add_crl() adds the CRL I<crl> to the B<PKCS7> structure I<p7>.
-This may be called to provide certificate status information
-to be included when signing or to use when verifying the B<PKCS7> structure.
+Certificates and CRLs are added to the I<cert> or
+I<crl> fields of B<PKCS7_SIGNED> or B<PKCS7_SIGN_ENVELOPE> structures.
=head1 RETURN VALUES
-PKCS7_sign_add_signers() returns an internal pointer to the B<PKCS7_SIGNER_INFO>
-structure just added or NULL if an error occurs.
+PKCS7_sign_add_signer() returns an internal pointer to the B<PKCS7_SIGNER_INFO>
+structure just added (which can be used to set additional attributes
+before it is finalized), or NULL if an error occurs.
PKCS7_add_certificate() and PKCS7_add_crl() return 1 on success, 0 on error.
diff --git a/doc/man3/PKCS7_verify.pod b/doc/man3/PKCS7_verify.pod
index 78af1794cd..ead63cd04f 100644
--- a/doc/man3/PKCS7_verify.pod
+++ b/doc/man3/PKCS7_verify.pod
@@ -21,8 +21,8 @@ PKCS7_verify, PKCS7_dataVerify, PKCS7_get0_signers - verify a PKCS#7 signedData
PKCS7_verify() is very similar to L<CMS_verify(3)>.
It verifies a PKCS#7 signedData structure given in I<p7>.
-The optional I<certs> parameter refers to a set of certificates
-in which to search for signer's certificates.
+The optional I<certs> parameter can provide a list of certificates,
+which is searched first for signer's certificates.
It is also used
as a source of untrusted intermediate CA certificates for chain building.
I<p7> may contain extra untrusted CA certificates that may be used for
@@ -34,9 +34,13 @@ Otherwise I<indata> should be NULL, and then the signed data must be in I<p7>.
The content is written to the BIO I<out> unless it is NULL.
I<flags> is an optional set of flags, which can be used to modify the operation.
-PKCS7_get0_signers() retrieves the signer certificates from I<p7>, it does
+PKCS7_get0_signers() retrieves the signer certificates from I<p7>
+by matching the pairs of certificate issuer and serial number contained in
+the SignerInfos with available candidate signer certificates. It does
B<not> check their validity or whether any signatures are valid. The I<certs>
and I<flags> parameters have the same meanings as in PKCS7_verify().
+If the result is not NULL, the caller must free the structure returned using
+sk_X509_free(), but must not free the certificates included there.
PKCS7_dataVerify() operates in a similar fashion to PKCS7_verify, with a few
notable exceptions:
@@ -68,10 +72,10 @@ B<PKCS7_NO_DUAL_CONTENT>.
The default behavior allows this, for compatibility with older
versions of OpenSSL.
-An attempt is made to locate all the signer's certificates, first looking in
+An attempt is made to locate all the signer certificates, first looking in
the I<certs> parameter (if it is not NULL). Then they are looked up in any
certificates contained in the I<p7> structure unless B<PKCS7_NOINTERN> is set.
-If any signer's certificates cannot be located the operation fails.
+If any signer certificates cannot be located the operation fails.
Each signer certificate is chain verified
using I<store> as the trusted certificate store if supplied.
@@ -96,8 +100,8 @@ parameter to change the default verify behaviour.
Only the flag B<PKCS7_NOINTERN> is meaningful to PKCS7_get0_signers().
If B<PKCS7_NOINTERN> is set the certificates in the message itself are not
-searched when locating the signer's certificates.
-This means that all the signer's certificates must be in the I<certs> parameter.
+searched when locating the signer certificates.
+This means that all the signer certificates must be in the I<certs> parameter.
If B<PKCS7_NOCRL> is set and CRL checking is enabled in I<store> then any
CRLs in the message itself are ignored.
@@ -106,11 +110,10 @@ If the B<PKCS7_TEXT> flag is set MIME headers for type C<text/plain> are deleted
from the content. If the content is not of type C<text/plain> then an error is
returned.
-If B<PKCS7_NOVERIFY> is set the signer's certificates are not chain verified.
+If B<PKCS7_NOVERIFY> is set the signer certificates are not chain verified.
If B<PKCS7_NOCHAIN> is set then the certificates contained in the message are
-not used as untrusted CAs. This means that the whole verify chain (apart from
-the signer's certificates) must be contained in the trusted store.
+not used as untrusted CA certificates for chain building.
If B<PKCS7_NOSIGS> is set then the signatures on the data are not checked.
@@ -118,7 +121,7 @@ If B<PKCS7_NOSIGS> is set then the signatures on the data are not checked.
One application of B<PKCS7_NOINTERN> is to only accept messages signed by
a small number of certificates. The acceptable certificates would be passed
-in the I<certs> parameter. In this case if the signer's certificate is not one
+in the I<certs> parameter. In this case, if the signer's certificate is not one
of the certificates supplied in I<certs> then the verify will fail because the
signer cannot be found.
@@ -144,7 +147,7 @@ The error can be obtained from L<ERR_get_error(3)>.
=head1 BUGS
-The trusted certificate store is not searched for the signer's certificates.
+The trusted certificate store is not searched for the signer certificates.
This is primarily due to the inadequacies of the current B<X509_STORE>
functionality.
diff --git a/include/openssl/pkcs7.h.in b/include/openssl/pkcs7.h.in
index f0b1c13de9..c9edcdd7ac 100644
--- a/include/openssl/pkcs7.h.in
+++ b/include/openssl/pkcs7.h.in
@@ -91,6 +91,7 @@ typedef struct pkcs7_recip_info_st {
typedef struct pkcs7_signed_st {
ASN1_INTEGER *version; /* version 1 */
STACK_OF(X509_ALGOR) *md_algs; /* md used */
+ /* untrusted certificates for chain building, may include signer certs: */
STACK_OF(X509) *cert; /* [ 0 ] */ /* name should be 'certificates' */
STACK_OF(X509_CRL) *crl; /* [ 1 ] */ /* name should be 'crls' */
STACK_OF(PKCS7_SIGNER_INFO) *signer_info;
@@ -118,6 +119,7 @@ typedef struct pkcs7_enveloped_st {
typedef struct pkcs7_signedandenveloped_st {
ASN1_INTEGER *version; /* version 1 */
STACK_OF(X509_ALGOR) *md_algs; /* md used */
+ /* untrusted certificates for chain building, may include signer certs: */
STACK_OF(X509) *cert; /* [ 0 ] */ /* name should be 'certificates' */
STACK_OF(X509_CRL) *crl; /* [ 1 ] */ /* name should be 'crls' */
STACK_OF(PKCS7_SIGNER_INFO) *signer_info;