Merge remote-tracking branch 'origin/development' into pr3431
diff --git a/include/mbedtls/asn1.h b/include/mbedtls/asn1.h
index 8b66ee2..5e3f387 100644
--- a/include/mbedtls/asn1.h
+++ b/include/mbedtls/asn1.h
@@ -39,8 +39,9 @@
/**
* \name ASN1 Error codes
- * These error codes are OR'ed to X509 error codes for
+ * These error codes are combined with other error codes for
* higher error granularity.
+ * e.g. X.509 and PKCS #7 error codes
* ASN1 is a standard to specify data structures.
* \{
*/
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index d36db4a..701bded 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -1062,6 +1062,14 @@
#error "MBEDTLS_SSL_TRUNCATED_HMAC was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4341"
#endif
+#if defined(MBEDTLS_PKCS7_C) && ( ( !defined(MBEDTLS_ASN1_PARSE_C) ) || \
+ ( !defined(MBEDTLS_OID_C) ) || ( !defined(MBEDTLS_PK_PARSE_C) ) || \
+ ( !defined(MBEDTLS_X509_CRT_PARSE_C) ) ||\
+ ( !defined(MBEDTLS_X509_CRL_PARSE_C) ) || ( !defined(MBEDTLS_BIGNUM_C) ) \
+ ( !defined(MBEDTLS_MD_C) ) )
+#error "MBEDTLS_PKCS7_C is defined, but not all prerequisites"
+#endif
+
/*
* Avoid warning from -pedantic. This is a convenient place for this
* workaround since this is included by every single file before the
diff --git a/include/mbedtls/error.h b/include/mbedtls/error.h
index eb83913..841b75b 100644
--- a/include/mbedtls/error.h
+++ b/include/mbedtls/error.h
@@ -96,6 +96,7 @@
* ECP 4 10 (Started from top)
* MD 5 5
* HKDF 5 1 (Started from top)
+ * PKCS7 5 12 (Started from 0x5300)
* SSL 5 2 (Started from 0x5F00)
* CIPHER 6 8 (Started from 0x6080)
* SSL 6 22 (Started from top, plus 0x6000)
diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h
index b4c8635..6a4f584 100644
--- a/include/mbedtls/mbedtls_config.h
+++ b/include/mbedtls/mbedtls_config.h
@@ -2781,6 +2781,22 @@
#define MBEDTLS_PKCS5_C
/**
+ * \def MBEDTLS_PKCS7_C
+ *
+ * Enable PKCS7 core for using PKCS7 formatted signatures.
+ * RFC Link - https://tools.ietf.org/html/rfc2315
+ *
+ * Module: library/pkcs7.c
+ *
+ * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_OID_C, MBEDTLS_PK_PARSE_C,
+ * MBEDTLS_X509_CRT_PARSE_C MBEDTLS_X509_CRL_PARSE_C,
+ * MBEDTLS_BIGNUM_C, MBEDTLS_MD_C
+ *
+ * This module is required for the PKCS7 parsing modules.
+ */
+#define MBEDTLS_PKCS7_C
+
+/**
* \def MBEDTLS_PKCS12_C
*
* Enable PKCS#12 PBE functions.
diff --git a/include/mbedtls/oid.h b/include/mbedtls/oid.h
index 4ee3f93..e5c4b92 100644
--- a/include/mbedtls/oid.h
+++ b/include/mbedtls/oid.h
@@ -220,6 +220,7 @@
#define MBEDTLS_OID_PKCS MBEDTLS_OID_RSA_COMPANY "\x01" /**< pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) 1 } */
#define MBEDTLS_OID_PKCS1 MBEDTLS_OID_PKCS "\x01" /**< pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } */
#define MBEDTLS_OID_PKCS5 MBEDTLS_OID_PKCS "\x05" /**< pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } */
+#define MBEDTLS_OID_PKCS7 MBEDTLS_OID_PKCS "\x07" /**< pkcs-7 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 7 } */
#define MBEDTLS_OID_PKCS9 MBEDTLS_OID_PKCS "\x09" /**< pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } */
#define MBEDTLS_OID_PKCS12 MBEDTLS_OID_PKCS "\x0c" /**< pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } */
@@ -301,6 +302,16 @@
#define MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5 "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */
/*
+ * PKCS#7 OIDs
+ */
+#define MBEDTLS_OID_PKCS7_DATA MBEDTLS_OID_PKCS7 "\x01" /**< Content type is Data OBJECT IDENTIFIER ::= {pkcs-7 1} */
+#define MBEDTLS_OID_PKCS7_SIGNED_DATA MBEDTLS_OID_PKCS7 "\x02" /**< Content type is Signed Data OBJECT IDENTIFIER ::= {pkcs-7 2} */
+#define MBEDTLS_OID_PKCS7_ENVELOPED_DATA MBEDTLS_OID_PKCS7 "\x03" /**< Content type is Enveloped Data OBJECT IDENTIFIER ::= {pkcs-7 3} */
+#define MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA MBEDTLS_OID_PKCS7 "\x04" /**< Content type is Signed and Enveloped Data OBJECT IDENTIFIER ::= {pkcs-7 4} */
+#define MBEDTLS_OID_PKCS7_DIGESTED_DATA MBEDTLS_OID_PKCS7 "\x05" /**< Content type is Digested Data OBJECT IDENTIFIER ::= {pkcs-7 5} */
+#define MBEDTLS_OID_PKCS7_ENCRYPTED_DATA MBEDTLS_OID_PKCS7 "\x06" /**< Content type is Encrypted Data OBJECT IDENTIFIER ::= {pkcs-7 6} */
+
+/*
* PKCS#8 OIDs
*/
#define MBEDTLS_OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9 "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */
diff --git a/include/mbedtls/pkcs7.h b/include/mbedtls/pkcs7.h
new file mode 100644
index 0000000..52895ac
--- /dev/null
+++ b/include/mbedtls/pkcs7.h
@@ -0,0 +1,241 @@
+/**
+ * \file pkcs7.h
+ *
+ * \brief PKCS7 generic defines and structures
+ * https://tools.ietf.org/html/rfc2315
+ */
+/*
+ * Copyright The Mbed TLS Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Note: For the time being, this implementation of the PKCS7 cryptographic
+ * message syntax is a partial implementation of RFC 2315.
+ * Differences include:
+ * - The RFC specifies 6 different content types. The only type currently
+ * supported in Mbed TLS is the signed data content type.
+ * - The only supported PKCS7 Signed Data syntax version is version 1
+ * - The RFC specifies support for BER. This implementation is limited to
+ * DER only.
+ * - The RFC specifies that multiple digest algorithms can be specified
+ * in the Signed Data type. Only one digest algorithm is supported in Mbed TLS.
+ * - The RFC specifies the Signed Data type can contain multiple X509 or PKCS6
+ * certificates. In Mbed TLS, this list can only contain 0 or 1 certificates
+ * and they must be in X509 format.
+ * - The RFC specifies the Signed Data type can contain
+ * certificate-revocation lists (crls). This implementation has no support
+ * for crls so it is assumed to be an empty list.
+ * - The RFC allows for SignerInfo structure to optionally contain
+ * unauthenticatedAttributes and authenticatedAttributes. In Mbed TLS it is
+ * assumed these fields are empty.
+ */
+
+#ifndef MBEDTLS_PKCS7_H
+#define MBEDTLS_PKCS7_H
+
+#include "mbedtls/private_access.h"
+
+#include "mbedtls/build_info.h"
+
+#include "mbedtls/asn1.h"
+#include "mbedtls/x509.h"
+#include "mbedtls/x509_crt.h"
+
+/**
+ * \name PKCS7 Module Error codes
+ * \{
+ */
+#define MBEDTLS_ERR_PKCS7_INVALID_FORMAT -0x5300 /**< The format is invalid, e.g. different type expected. */
+#define MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE -0x5380 /**< Unavailable feature, e.g. anything other than signed data. */
+#define MBEDTLS_ERR_PKCS7_INVALID_VERSION -0x5400 /**< The PKCS7 version element is invalid or cannot be parsed. */
+#define MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO -0x5480 /**< The PKCS7 content info invalid or cannot be parsed. */
+#define MBEDTLS_ERR_PKCS7_INVALID_ALG -0x5500 /**< The algorithm tag or value is invalid or cannot be parsed. */
+#define MBEDTLS_ERR_PKCS7_INVALID_CERT -0x5580 /**< The certificate tag or value is invalid or cannot be parsed. */
+#define MBEDTLS_ERR_PKCS7_INVALID_SIGNATURE -0x5600 /**< Error parsing the signature */
+#define MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO -0x5680 /**< Error parsing the signer's info */
+#define MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA -0x5700 /**< Input invalid. */
+#define MBEDTLS_ERR_PKCS7_ALLOC_FAILED -0x5780 /**< Allocation of memory failed. */
+#define MBEDTLS_ERR_PKCS7_VERIFY_FAIL -0x5800 /**< Verification Failed */
+#define MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID -0x5880 /**< The PKCS7 date issued/expired dates are invalid */
+/* \} name */
+
+/**
+ * \name PKCS7 Supported Version
+ * \{
+ */
+#define MBEDTLS_PKCS7_SUPPORTED_VERSION 0x01
+/* \} name */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Type-length-value structure that allows for ASN1 using DER.
+ */
+typedef mbedtls_asn1_buf mbedtls_pkcs7_buf;
+
+/**
+ * Container for ASN1 named information objects.
+ * It allows for Relative Distinguished Names (e.g. cn=localhost,ou=code,etc.).
+ */
+typedef mbedtls_asn1_named_data mbedtls_pkcs7_name;
+
+/**
+ * Container for a sequence of ASN.1 items
+ */
+typedef mbedtls_asn1_sequence mbedtls_pkcs7_sequence;
+
+/**
+ * PKCS7 types
+ */
+typedef enum {
+ MBEDTLS_PKCS7_NONE=0,
+ MBEDTLS_PKCS7_DATA,
+ MBEDTLS_PKCS7_SIGNED_DATA,
+ MBEDTLS_PKCS7_ENVELOPED_DATA,
+ MBEDTLS_PKCS7_SIGNED_AND_ENVELOPED_DATA,
+ MBEDTLS_PKCS7_DIGESTED_DATA,
+ MBEDTLS_PKCS7_ENCRYPTED_DATA,
+}
+mbedtls_pkcs7_type;
+
+/**
+ * Structure holding PKCS7 signer info
+ */
+typedef struct mbedtls_pkcs7_signer_info
+{
+ int MBEDTLS_PRIVATE(version);
+ mbedtls_x509_buf MBEDTLS_PRIVATE(serial);
+ mbedtls_x509_name MBEDTLS_PRIVATE(issuer);
+ mbedtls_x509_buf MBEDTLS_PRIVATE(issuer_raw);
+ mbedtls_x509_buf MBEDTLS_PRIVATE(alg_identifier);
+ mbedtls_x509_buf MBEDTLS_PRIVATE(sig_alg_identifier);
+ mbedtls_x509_buf MBEDTLS_PRIVATE(sig);
+ struct mbedtls_pkcs7_signer_info *MBEDTLS_PRIVATE(next);
+}
+mbedtls_pkcs7_signer_info;
+
+/**
+ * Structure holding attached data as part of PKCS7 signed data format
+ */
+typedef struct mbedtls_pkcs7_data
+{
+ mbedtls_pkcs7_buf MBEDTLS_PRIVATE(oid);
+ mbedtls_pkcs7_buf MBEDTLS_PRIVATE(data);
+}
+mbedtls_pkcs7_data;
+
+/**
+ * Structure holding the signed data section
+ */
+typedef struct mbedtls_pkcs7_signed_data
+{
+ int MBEDTLS_PRIVATE(version);
+ mbedtls_pkcs7_buf MBEDTLS_PRIVATE(digest_alg_identifiers);
+ struct mbedtls_pkcs7_data MBEDTLS_PRIVATE(content);
+ int MBEDTLS_PRIVATE(no_of_certs);
+ mbedtls_x509_crt MBEDTLS_PRIVATE(certs);
+ int MBEDTLS_PRIVATE(no_of_crls);
+ mbedtls_x509_crl MBEDTLS_PRIVATE(crl);
+ int MBEDTLS_PRIVATE(no_of_signers);
+ mbedtls_pkcs7_signer_info MBEDTLS_PRIVATE(signers);
+}
+mbedtls_pkcs7_signed_data;
+
+/**
+ * Structure holding PKCS7 structure, only signed data for now
+ */
+typedef struct mbedtls_pkcs7
+{
+ mbedtls_pkcs7_buf MBEDTLS_PRIVATE(raw);
+ mbedtls_pkcs7_buf MBEDTLS_PRIVATE(content_type_oid);
+ mbedtls_pkcs7_signed_data MBEDTLS_PRIVATE(signed_data);
+}
+mbedtls_pkcs7;
+
+/**
+ * \brief Initialize pkcs7 structure.
+ *
+ * \param pkcs7 pkcs7 structure.
+ */
+void mbedtls_pkcs7_init( mbedtls_pkcs7 *pkcs7 );
+
+/**
+ * \brief Parse a single DER formatted pkcs7 content.
+ *
+ * \param pkcs7 The pkcs7 structure to be filled by parser for the output.
+ * \param buf The buffer holding the DER encoded pkcs7.
+ * \param buflen The size in Bytes of \p buf.
+ *
+ * \note This function makes an internal copy of the PKCS7 buffer
+ * \p buf. In particular, \p buf may be destroyed or reused
+ * after this call returns.
+ *
+ * \return The \c mbedtls_pkcs7_type of \p buf, if successful.
+ * \return A negative error code on failure.
+ */
+int mbedtls_pkcs7_parse_der( mbedtls_pkcs7 *pkcs7, const unsigned char *buf,
+ const size_t buflen );
+
+/**
+ * \brief Verification of PKCS7 signature.
+ *
+ * \param pkcs7 PKCS7 structure containing signature.
+ * \param cert Certificate containing key to verify signature.
+ * \param data Plain data on which signature has to be verified.
+ * \param datalen Length of the data.
+ *
+ * \note This function internally calculates the hash on the supplied
+ * plain data for signature verification.
+ *
+ * \return A negative error code on failure.
+ */
+int mbedtls_pkcs7_signed_data_verify( mbedtls_pkcs7 *pkcs7,
+ const mbedtls_x509_crt *cert,
+ const unsigned char *data,
+ size_t datalen );
+
+/**
+ * \brief Verification of PKCS7 signature.
+ *
+ * \param pkcs7 PKCS7 structure containing signature.
+ * \param cert Certificate containing key to verify signature.
+ * \param hash Hash of the plain data on which signature has to be verified.
+ * \param hashlen Length of the hash.
+ *
+ * \note This function is different from mbedtls_pkcs7_signed_data_verify()
+ * in a way that it directly recieves the hash of the data.
+ *
+ * \return A negative error code on failure.
+ */
+int mbedtls_pkcs7_signed_hash_verify( mbedtls_pkcs7 *pkcs7,
+ const mbedtls_x509_crt *cert,
+ const unsigned char *hash, size_t hashlen);
+
+/**
+ * \brief Unallocate all PKCS7 data and zeroize the memory.
+ * It doesn't free pkcs7 itself. It should be done by the caller.
+ *
+ * \param pkcs7 PKCS7 structure to free.
+ */
+void mbedtls_pkcs7_free( mbedtls_pkcs7 *pkcs7 );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* pkcs7.h */
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 7c325f7..60b1cf4 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -92,6 +92,7 @@
)
set(src_x509
+ pkcs7.c
x509.c
x509_create.c
x509_crl.c
diff --git a/library/Makefile b/library/Makefile
index b1cdc7f..6c3b758 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -168,6 +168,7 @@
x509_csr.o \
x509write_crt.o \
x509write_csr.o \
+ pkcs7.o \
# This line is intentionally left blank
OBJS_TLS= \
diff --git a/library/pkcs7.c b/library/pkcs7.c
new file mode 100644
index 0000000..ca0170a
--- /dev/null
+++ b/library/pkcs7.c
@@ -0,0 +1,753 @@
+/*
+ * Copyright The Mbed TLS Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "common.h"
+
+#include "mbedtls/build_info.h"
+#if defined(MBEDTLS_PKCS7_C)
+#include "mbedtls/pkcs7.h"
+#include "mbedtls/x509.h"
+#include "mbedtls/asn1.h"
+#include "mbedtls/x509_crt.h"
+#include "mbedtls/x509_crl.h"
+#include "mbedtls/oid.h"
+#include "mbedtls/error.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#if defined(MBEDTLS_FS_IO)
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+
+#include "mbedtls/platform.h"
+#include "mbedtls/platform_util.h"
+
+#if defined(MBEDTLS_HAVE_TIME)
+#include "mbedtls/platform_time.h"
+#endif
+#if defined(MBEDTLS_HAVE_TIME_DATE)
+#include <time.h>
+#endif
+
+/**
+ * Initializes the pkcs7 structure.
+ */
+void mbedtls_pkcs7_init( mbedtls_pkcs7 *pkcs7 )
+{
+ memset( pkcs7, 0, sizeof( *pkcs7 ) );
+}
+
+static int pkcs7_get_next_content_len( unsigned char **p, unsigned char *end,
+ size_t *len )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_CONSTRUCTED
+ | MBEDTLS_ASN1_CONTEXT_SPECIFIC );
+ if( ret != 0 )
+ {
+ ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret );
+ }
+
+ return( ret );
+}
+
+/**
+ * version Version
+ * Version ::= INTEGER
+ **/
+static int pkcs7_get_version( unsigned char **p, unsigned char *end, int *ver )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ ret = mbedtls_asn1_get_int( p, end, ver );
+ if( ret != 0 )
+ ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_VERSION, ret );
+
+ /* If version != 1, return invalid version */
+ if( *ver != MBEDTLS_PKCS7_SUPPORTED_VERSION )
+ ret = MBEDTLS_ERR_PKCS7_INVALID_VERSION;
+
+ return( ret );
+}
+
+/**
+ * ContentInfo ::= SEQUENCE {
+ * contentType ContentType,
+ * content
+ * [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+ **/
+static int pkcs7_get_content_info_type( unsigned char **p, unsigned char *end,
+ mbedtls_pkcs7_buf *pkcs7 )
+{
+ size_t len = 0;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ unsigned char *start = *p;
+
+ ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
+ | MBEDTLS_ASN1_SEQUENCE );
+ if( ret != 0 ) {
+ *p = start;
+ ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret );
+ goto out;
+ }
+
+ ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_OID );
+ if( ret != 0 ) {
+ *p = start;
+ ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret );
+ goto out;
+ }
+
+ pkcs7->tag = MBEDTLS_ASN1_OID;
+ pkcs7->len = len;
+ pkcs7->p = *p;
+ *p += len;
+
+out:
+ return( ret );
+}
+
+/**
+ * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+ *
+ * This is from x509.h
+ **/
+static int pkcs7_get_digest_algorithm( unsigned char **p, unsigned char *end,
+ mbedtls_x509_buf *alg )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 )
+ ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_ALG, ret );
+
+ return( ret );
+}
+
+/**
+ * DigestAlgorithmIdentifiers :: SET of DigestAlgorithmIdentifier
+ **/
+static int pkcs7_get_digest_algorithm_set( unsigned char **p,
+ unsigned char *end,
+ mbedtls_x509_buf *alg )
+{
+ size_t len = 0;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
+ | MBEDTLS_ASN1_SET );
+ if( ret != 0 )
+ {
+ ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_ALG, ret );
+ goto out;
+ }
+
+ end = *p + len;
+
+ ret = mbedtls_asn1_get_alg_null( p, end, alg );
+ if( ret != 0 )
+ {
+ ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_ALG, ret );
+ goto out;
+ }
+
+ /** For now, it assumes there is only one digest algorithm specified **/
+ if ( *p != end )
+ ret = MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
+
+out:
+ return( ret );
+}
+
+/**
+ * certificates :: SET OF ExtendedCertificateOrCertificate,
+ * ExtendedCertificateOrCertificate ::= CHOICE {
+ * certificate Certificate -- x509,
+ * extendedCertificate[0] IMPLICIT ExtendedCertificate }
+ * Return number of certificates added to the signed data,
+ * 0 or higher is valid.
+ * Return negative error code for failure.
+ **/
+static int pkcs7_get_certificates( unsigned char **p, unsigned char *end,
+ mbedtls_x509_crt *certs )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t len1 = 0;
+ size_t len2 = 0;
+ unsigned char *end_set, *end_cert, *start;
+
+ if( ( ret = mbedtls_asn1_get_tag( p, end, &len1, MBEDTLS_ASN1_CONSTRUCTED
+ | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 )
+ {
+ if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
+ ret = 0;
+ else
+ ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret );
+ goto out;
+ }
+ start = *p;
+ end_set = *p + len1;
+
+ ret = mbedtls_asn1_get_tag( p, end_set, &len2, MBEDTLS_ASN1_CONSTRUCTED
+ | MBEDTLS_ASN1_SEQUENCE );
+ if( ret != 0 )
+ {
+ ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_CERT, ret );
+ goto out;
+ }
+
+ end_cert = *p + len2;
+
+ /*
+ * This is to verify that there is only one signer certificate. It seems it is
+ * not easy to differentiate between the chain vs different signer's certificate.
+ * So, we support only the root certificate and the single signer.
+ * The behaviour would be improved with addition of multiple signer support.
+ */
+ if ( end_cert != end_set )
+ {
+ ret = MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
+ goto out;
+ }
+
+ *p = start;
+ if( ( ret = mbedtls_x509_crt_parse_der( certs, *p, len1 ) ) < 0 )
+ {
+ ret = MBEDTLS_ERR_PKCS7_INVALID_CERT;
+ goto out;
+ }
+
+ *p = *p + len1;
+
+ /*
+ * Since in this version we strictly support single certificate, and reaching
+ * here implies we have parsed successfully, we return 1.
+ */
+ ret = 1;
+
+out:
+ return( ret );
+}
+
+/**
+ * EncryptedDigest ::= OCTET STRING
+ **/
+static int pkcs7_get_signature( unsigned char **p, unsigned char *end,
+ mbedtls_pkcs7_buf *signature )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t len = 0;
+
+ ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_OCTET_STRING );
+ if( ret != 0 )
+ goto out;
+
+ signature->tag = MBEDTLS_ASN1_OCTET_STRING;
+ signature->len = len;
+ signature->p = *p;
+
+ *p = *p + len;
+
+out:
+ return( ret );
+}
+
+/**
+ * SignerInfo ::= SEQUENCE {
+ * version Version;
+ * issuerAndSerialNumber IssuerAndSerialNumber,
+ * digestAlgorithm DigestAlgorithmIdentifier,
+ * authenticatedAttributes
+ * [0] IMPLICIT Attributes OPTIONAL,
+ * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
+ * encryptedDigest EncryptedDigest,
+ * unauthenticatedAttributes
+ * [1] IMPLICIT Attributes OPTIONAL,
+ * Returns 0 if the signerInfo is valid.
+ * Return negative error code for failure.
+ * Structure must not contain vales for authenticatedAttributes
+ * and unauthenticatedAttributes.
+ **/
+static int pkcs7_get_signer_info( unsigned char **p, unsigned char *end,
+ mbedtls_pkcs7_signer_info *signer )
+{
+ unsigned char *end_signer;
+ int asn1_ret = 0, ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t len = 0;
+
+ asn1_ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
+ | MBEDTLS_ASN1_SEQUENCE );
+ if( asn1_ret != 0 )
+ goto out;
+
+ end_signer = *p + len;
+
+ ret = pkcs7_get_version( p, end_signer, &signer->version );
+ if( ret != 0 )
+ goto out;
+
+ asn1_ret = mbedtls_asn1_get_tag( p, end_signer, &len,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
+ if( asn1_ret != 0 )
+ goto out;
+
+ /* Parsing IssuerAndSerialNumber */
+ signer->issuer_raw.p = *p;
+
+ asn1_ret = mbedtls_asn1_get_tag( p, end_signer, &len,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
+ if( asn1_ret != 0 )
+ goto out;
+
+ ret = mbedtls_x509_get_name( p, *p + len, &signer->issuer );
+ if( ret != 0 )
+ goto out;
+
+ signer->issuer_raw.len = *p - signer->issuer_raw.p;
+
+ ret = mbedtls_x509_get_serial( p, end_signer, &signer->serial );
+ if( ret != 0 )
+ goto out;
+
+ ret = pkcs7_get_digest_algorithm( p, end_signer, &signer->alg_identifier );
+ if( ret != 0 )
+ goto out;
+
+ /* Asssume authenticatedAttributes is nonexistent */
+
+ ret = pkcs7_get_digest_algorithm( p, end_signer, &signer->sig_alg_identifier );
+ if( ret != 0 )
+ goto out;
+
+ ret = pkcs7_get_signature( p, end_signer, &signer->sig );
+ if( ret != 0 )
+ goto out;
+
+ /* Do not permit any unauthenticated attributes */
+ if( *p != end_signer )
+ ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
+
+out:
+ if( asn1_ret != 0 )
+ ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO,
+ asn1_ret );
+ else if( ret != 0 )
+ ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
+
+ return( ret );
+}
+
+static void pkcs7_free_signer_info( mbedtls_pkcs7_signer_info *signer )
+{
+ mbedtls_x509_name *name_cur;
+ mbedtls_x509_name *name_prv;
+
+ if( signer == NULL )
+ return;
+
+ name_cur = signer->issuer.next;
+ while( name_cur != NULL )
+ {
+ name_prv = name_cur;
+ name_cur = name_cur->next;
+ mbedtls_free( name_prv );
+ }
+}
+
+/**
+ * SignerInfos ::= SET of SignerInfo
+ * Return number of signers added to the signed data,
+ * 0 or higher is valid.
+ * Return negative error code for failure.
+ **/
+static int pkcs7_get_signers_info_set( unsigned char **p, unsigned char *end,
+ mbedtls_pkcs7_signer_info *signers_set )
+{
+ unsigned char *end_set;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ int count = 0;
+ size_t len = 0;
+ mbedtls_pkcs7_signer_info *signer, *prev;
+
+ ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
+ | MBEDTLS_ASN1_SET );
+ if( ret != 0 )
+ {
+ ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO, ret );
+ goto out;
+ }
+
+ /* Detect zero signers */
+ if( len == 0 )
+ {
+ ret = 0;
+ goto out;
+ }
+
+ end_set = *p + len;
+
+ ret = pkcs7_get_signer_info( p, end_set, signers_set );
+ if( ret != 0 )
+ goto out;
+ count++;
+
+ prev = signers_set;
+ while( *p != end_set )
+ {
+ signer = mbedtls_calloc( 1, sizeof( mbedtls_pkcs7_signer_info ) );
+ if( !signer )
+ {
+ ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
+ goto cleanup;
+ }
+
+ ret = pkcs7_get_signer_info( p, end_set, signer );
+ if( ret != 0 ) {
+ mbedtls_free( signer );
+ goto cleanup;
+ }
+ prev->next = signer;
+ prev = signer;
+ count++;
+ }
+
+ ret = count;
+ goto out;
+
+cleanup:
+ signer = signers_set->next;
+ pkcs7_free_signer_info( signers_set );
+ while( signer )
+ {
+ prev = signer;
+ signer = signer->next;
+ pkcs7_free_signer_info( prev );
+ mbedtls_free( prev );
+ }
+
+out:
+ return( ret );
+}
+
+/**
+ * SignedData ::= SEQUENCE {
+ * version Version,
+ * digestAlgorithms DigestAlgorithmIdentifiers,
+ * contentInfo ContentInfo,
+ * certificates
+ * [0] IMPLICIT ExtendedCertificatesAndCertificates
+ * OPTIONAL,
+ * crls
+ * [0] IMPLICIT CertificateRevocationLists OPTIONAL,
+ * signerInfos SignerInfos }
+ */
+static int pkcs7_get_signed_data( unsigned char *buf, size_t buflen,
+ mbedtls_pkcs7_signed_data *signed_data )
+{
+ unsigned char *p = buf;
+ unsigned char *end = buf + buflen;
+ unsigned char *end_set;
+ size_t len = 0;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ mbedtls_md_type_t md_alg;
+
+ ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
+ | MBEDTLS_ASN1_SEQUENCE );
+ if( ret != 0 )
+ {
+ ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret );
+ goto out;
+ }
+
+ end_set = p + len;
+
+ /* Get version of signed data */
+ ret = pkcs7_get_version( &p, end_set, &signed_data->version );
+ if( ret != 0 )
+ goto out;
+
+ /* Get digest algorithm */
+ ret = pkcs7_get_digest_algorithm_set( &p, end_set,
+ &signed_data->digest_alg_identifiers );
+ if( ret != 0 )
+ goto out;
+
+ ret = mbedtls_oid_get_md_alg( &signed_data->digest_alg_identifiers, &md_alg );
+ if( ret != 0 )
+ {
+ ret = MBEDTLS_ERR_PKCS7_INVALID_ALG;
+ goto out;
+ }
+
+ /* Do not expect any content */
+ ret = pkcs7_get_content_info_type( &p, end_set, &signed_data->content.oid );
+ if( ret != 0 )
+ goto out;
+
+ if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_DATA, &signed_data->content.oid ) )
+ {
+ ret = MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO;
+ goto out;
+ }
+
+ /* Look for certificates, there may or may not be any */
+ mbedtls_x509_crt_init( &signed_data->certs );
+ ret = pkcs7_get_certificates( &p, end_set, &signed_data->certs );
+ if( ret < 0 )
+ goto out;
+
+ signed_data->no_of_certs = ret;
+
+ /*
+ * Currently CRLs are not supported. If CRL exist, the parsing will fail
+ * at next step of getting signers info and return error as invalid
+ * signer info.
+ */
+
+ signed_data->no_of_crls = 0;
+
+ /* Get signers info */
+ ret = pkcs7_get_signers_info_set( &p, end_set, &signed_data->signers );
+ if( ret < 0 )
+ goto out;
+
+ signed_data->no_of_signers = ret;
+
+ /* Don't permit trailing data */
+ if ( p != end )
+ ret = MBEDTLS_ERR_PKCS7_INVALID_FORMAT;
+ else
+ ret = 0;
+
+out:
+ return( ret );
+}
+
+int mbedtls_pkcs7_parse_der( mbedtls_pkcs7 *pkcs7, const unsigned char *buf,
+ const size_t buflen )
+{
+ unsigned char *p;
+ unsigned char *end;
+ size_t len = 0;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ int isoidset = 0;
+
+ if( !pkcs7 )
+ {
+ ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
+ goto out;
+ }
+
+ /* make an internal copy of the buffer for parsing */
+ pkcs7->raw.p = p = mbedtls_calloc( 1, buflen );
+ if( pkcs7->raw.p == NULL )
+ {
+ ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
+ goto out;
+ }
+ memcpy( p, buf, buflen );
+ pkcs7->raw.len = buflen;
+ end = p + buflen;
+
+ ret = pkcs7_get_content_info_type( &p, end, &pkcs7->content_type_oid );
+ if( ret != 0 )
+ {
+ len = buflen;
+ goto try_data;
+ }
+
+ if( ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_DATA, &pkcs7->content_type_oid )
+ || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, &pkcs7->content_type_oid )
+ || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_ENVELOPED_DATA, &pkcs7->content_type_oid )
+ || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA, &pkcs7->content_type_oid )
+ || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_DIGESTED_DATA, &pkcs7->content_type_oid )
+ || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, &pkcs7->content_type_oid ) )
+ {
+ ret = MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
+ goto out;
+ }
+
+ if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_SIGNED_DATA, &pkcs7->content_type_oid ) )
+ {
+ ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
+ goto out;
+ }
+
+ isoidset = 1;
+
+ ret = pkcs7_get_next_content_len( &p, end, &len );
+ if( ret != 0 )
+ goto out;
+
+try_data:
+ ret = pkcs7_get_signed_data( p, len, &pkcs7->signed_data );
+ if ( ret != 0 )
+ goto out;
+
+ if ( !isoidset )
+ {
+ pkcs7->content_type_oid.tag = MBEDTLS_ASN1_OID;
+ pkcs7->content_type_oid.len = MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS7_SIGNED_DATA );
+ pkcs7->content_type_oid.p = (unsigned char *)MBEDTLS_OID_PKCS7_SIGNED_DATA;
+ }
+
+ ret = MBEDTLS_PKCS7_SIGNED_DATA;
+
+out:
+ if ( ret < 0 )
+ mbedtls_pkcs7_free( pkcs7 );
+
+ return( ret );
+}
+
+static int mbedtls_pkcs7_data_or_hash_verify( mbedtls_pkcs7 *pkcs7,
+ const mbedtls_x509_crt *cert,
+ const unsigned char *data,
+ size_t datalen,
+ const int is_data_hash )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ unsigned char *hash;
+ mbedtls_pk_context pk_cxt = cert->pk;
+ const mbedtls_md_info_t *md_info;
+ mbedtls_md_type_t md_alg;
+ mbedtls_pkcs7_signer_info *signer;
+
+ if( pkcs7->signed_data.no_of_signers == 0 )
+ {
+ ret = MBEDTLS_ERR_PKCS7_INVALID_CERT;
+ goto out;
+ }
+
+ if( mbedtls_x509_time_is_past( &cert->valid_to ) ||
+ mbedtls_x509_time_is_future( &cert->valid_from ))
+ {
+ ret = MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID;
+ goto out;
+ }
+
+ /*
+ * Potential TODOs
+ * Currently we iterate over all signers and return success if any of them
+ * verify.
+ *
+ * However, we could make this better by checking against the certificate's
+ * identification and SignerIdentifier fields first. That would also allow
+ * us to distinguish between 'no signature for key' and 'signature for key
+ * failed to validate'.
+ *
+ * We could also cache hashes by md, so if there are several sigs all using
+ * the same algo we don't recalculate the hash each time.
+ */
+ for( signer = &pkcs7->signed_data.signers; signer; signer = signer->next )
+ {
+ ret = mbedtls_oid_get_md_alg( &signer->alg_identifier, &md_alg );
+ if( ret != 0 )
+ {
+ ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
+ continue;
+ }
+
+ md_info = mbedtls_md_info_from_type( md_alg );
+ if( md_info == NULL )
+ {
+ ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
+ continue;
+ }
+
+ hash = mbedtls_calloc( mbedtls_md_get_size( md_info ), 1 );
+ if( hash == NULL ) {
+ ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
+ goto out;
+ }
+ if( is_data_hash )
+ {
+ if( datalen != mbedtls_md_get_size( md_info ))
+ ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
+ else
+ memcpy(hash, data, datalen);
+ }
+ else
+ {
+ ret = mbedtls_md( md_info, data, datalen, hash );
+ }
+ if( ret != 0 )
+ {
+ ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
+ mbedtls_free( hash );
+ continue;
+ }
+
+ ret = mbedtls_pk_verify( &pk_cxt, md_alg, hash,
+ mbedtls_md_get_size( md_info ),
+ signer->sig.p, signer->sig.len );
+ mbedtls_free( hash );
+
+ if( ret == 0 )
+ break;
+ }
+
+out:
+ return( ret );
+}
+int mbedtls_pkcs7_signed_data_verify( mbedtls_pkcs7 *pkcs7,
+ const mbedtls_x509_crt *cert,
+ const unsigned char *data,
+ size_t datalen )
+{
+ return( mbedtls_pkcs7_data_or_hash_verify( pkcs7, cert, data, datalen, 0 ) );
+}
+
+int mbedtls_pkcs7_signed_hash_verify( mbedtls_pkcs7 *pkcs7,
+ const mbedtls_x509_crt *cert,
+ const unsigned char *hash,
+ size_t hashlen )
+{
+ return( mbedtls_pkcs7_data_or_hash_verify( pkcs7, cert, hash, hashlen, 1 ) );
+}
+
+/*
+ * Unallocate all pkcs7 data
+ */
+void mbedtls_pkcs7_free( mbedtls_pkcs7 *pkcs7 )
+{
+ mbedtls_pkcs7_signer_info *signer_cur;
+ mbedtls_pkcs7_signer_info *signer_prev;
+
+ if( pkcs7 == NULL || pkcs7->raw.p == NULL )
+ return;
+
+ mbedtls_free( pkcs7->raw.p );
+
+ mbedtls_x509_crt_free( &pkcs7->signed_data.certs );
+ mbedtls_x509_crl_free( &pkcs7->signed_data.crl );
+
+ signer_cur = pkcs7->signed_data.signers.next;
+ pkcs7_free_signer_info( &pkcs7->signed_data.signers );
+ while( signer_cur != NULL )
+ {
+ signer_prev = signer_cur;
+ signer_cur = signer_prev->next;
+ pkcs7_free_signer_info( signer_prev );
+ mbedtls_free( signer_prev );
+ }
+
+ pkcs7->raw.p = NULL;
+}
+
+#endif
diff --git a/programs/fuzz/.gitignore b/programs/fuzz/.gitignore
index 5dc0960..34e3ed0 100644
--- a/programs/fuzz/.gitignore
+++ b/programs/fuzz/.gitignore
@@ -1,6 +1,7 @@
fuzz_client
fuzz_dtlsclient
fuzz_dtlsserver
+fuzz_pkcs7
fuzz_privkey
fuzz_pubkey
fuzz_server
diff --git a/programs/fuzz/CMakeLists.txt b/programs/fuzz/CMakeLists.txt
index c7fcd35..7747744 100644
--- a/programs/fuzz/CMakeLists.txt
+++ b/programs/fuzz/CMakeLists.txt
@@ -12,6 +12,7 @@
fuzz_x509crl
fuzz_x509crt
fuzz_x509csr
+ fuzz_pkcs7
)
set(executables_with_common_c
diff --git a/programs/fuzz/fuzz_pkcs7.c b/programs/fuzz/fuzz_pkcs7.c
new file mode 100644
index 0000000..960007d
--- /dev/null
+++ b/programs/fuzz/fuzz_pkcs7.c
@@ -0,0 +1,19 @@
+#include <stdint.h>
+#include "mbedtls/pkcs7.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+#ifdef MBEDTLS_PKCS7_C
+ mbedtls_pkcs7 pkcs7;
+
+ mbedtls_pkcs7_init( &pkcs7 );
+
+ mbedtls_pkcs7_parse_der( &pkcs7, Data, Size );
+
+ mbedtls_pkcs7_free( &pkcs7 );
+#else
+ (void) Data;
+ (void) Size;
+#endif
+
+ return 0;
+}
diff --git a/programs/fuzz/fuzz_pkcs7.options b/programs/fuzz/fuzz_pkcs7.options
new file mode 100644
index 0000000..0824b19
--- /dev/null
+++ b/programs/fuzz/fuzz_pkcs7.options
@@ -0,0 +1,2 @@
+[libfuzzer]
+max_len = 65535
diff --git a/scripts/config.py b/scripts/config.py
index 470c63d..7e58acd 100755
--- a/scripts/config.py
+++ b/scripts/config.py
@@ -311,6 +311,7 @@
if name in [
'MBEDTLS_DEBUG_C', # part of libmbedtls
'MBEDTLS_NET_C', # part of libmbedtls
+ 'MBEDTLS_PKCS7_C', # part of libmbedx509
]:
return False
return True
diff --git a/scripts/generate_errors.pl b/scripts/generate_errors.pl
index 41b0337..5395abf 100755
--- a/scripts/generate_errors.pl
+++ b/scripts/generate_errors.pl
@@ -52,7 +52,7 @@
SHA1 SHA256 SHA512 THREADING );
my @high_level_modules = qw( CIPHER DHM ECP MD
PEM PK PKCS12 PKCS5
- RSA SSL X509 );
+ RSA SSL X509 PKCS7 );
undef $/;
@@ -136,6 +136,7 @@
$define_name = "ASN1_PARSE" if ($define_name eq "ASN1");
$define_name = "SSL_TLS" if ($define_name eq "SSL");
$define_name = "PEM_PARSE,PEM_WRITE" if ($define_name eq "PEM");
+ $define_name = "PKCS7" if ($define_name eq "PKCS7");
my $include_name = $module_name;
$include_name =~ tr/A-Z/a-z/;
diff --git a/tests/data_files/Makefile b/tests/data_files/Makefile
index 09a0689..c5924ec 100644
--- a/tests/data_files/Makefile
+++ b/tests/data_files/Makefile
@@ -1134,6 +1134,108 @@
all_final += ecdsa_secp521r1.crt ecdsa_secp521r1.key
tls13_certs: ecdsa_secp521r1.crt ecdsa_secp521r1.key
+# PKCS7 test data
+pkcs7_test_cert_1 = pkcs7-rsa-sha256-1.crt
+pkcs7_test_cert_2 = pkcs7-rsa-sha256-2.crt
+pkcs7_test_file = pkcs7_data.bin
+
+$(pkcs7_test_file):
+ echo -e "Hello\xd" > $@
+all_final += $(pkcs7_test_file)
+
+pkcs7_data_1.bin:
+ echo -e "2\xd" > $@
+all_final += pkcs7_data_1.bin
+
+# Generate signing cert
+pkcs7-rsa-sha256-1.crt:
+ $(OPENSSL) req -x509 -subj="/C=NL/O=PKCS7/CN=PKCS7 Cert 1" -sha256 -nodes -days 365 -newkey rsa:2048 -keyout pkcs7-rsa-sha256-1.key -out pkcs7-rsa-sha256-1.crt
+ cat pkcs7-rsa-sha256-1.crt pkcs7-rsa-sha256-1.key > pkcs7-rsa-sha256-1.pem
+all_final += pkcs7-rsa-sha256-1.crt
+
+pkcs7-rsa-sha256-2.crt:
+ $(OPENSSL) req -x509 -subj="/C=NL/O=PKCS7/CN=PKCS7 Cert 2" -sha256 -nodes -days 365 -newkey rsa:2048 -keyout pkcs7-rsa-sha256-2.key -out pkcs7-rsa-sha256-2.crt
+ cat pkcs7-rsa-sha256-2.crt pkcs7-rsa-sha256-2.key > pkcs7-rsa-sha256-2.pem
+all_final += pkcs7-rsa-sha256-2.crt
+
+# Convert signing certs to DER for testing PEM-free builds
+pkcs7-rsa-sha256-1.der: $(pkcs7_test_cert_1)
+ $(OPENSSL) x509 -in pkcs7-rsa-sha256-1.crt -out $@ -outform DER
+all_final += pkcs7-rsa-sha256-1.der
+
+pkcs7-rsa-sha256-2.der: $(pkcs7_test_cert_2)
+ $(OPENSSL) x509 -in pkcs7-rsa-sha256-2.crt -out $@ -outform DER
+all_final += pkcs7-rsa-sha256-2.der
+
+# pkcs7 signature file with CERT
+pkcs7_data_cert_signed_sha256.der: $(pkcs7_test_file) $(pkcs7_test_cert_1)
+ $(OPENSSL) smime -sign -binary -in pkcs7_data.bin -out $@ -md sha256 -signer pkcs7-rsa-sha256-1.pem -noattr -outform DER -out $@
+all_final += pkcs7_data_cert_signed_sha256.der
+
+# pkcs7 signature file with CERT and sha1
+pkcs7_data_cert_signed_sha1.der: $(pkcs7_test_file) $(pkcs7_test_cert_1)
+ $(OPENSSL) smime -sign -binary -in pkcs7_data.bin -out $@ -md sha1 -signer pkcs7-rsa-sha256-1.pem -noattr -outform DER -out $@
+all_final += pkcs7_data_cert_signed_sha1.der
+
+# pkcs7 signature file with CERT and sha512
+pkcs7_data_cert_signed_sha512.der: $(pkcs7_test_file) $(pkcs7_test_cert_1)
+ $(OPENSSL) smime -sign -binary -in pkcs7_data.bin -out $@ -md sha512 -signer pkcs7-rsa-sha256-1.pem -noattr -outform DER -out $@
+all_final += pkcs7_data_cert_signed_sha512.der
+
+# pkcs7 signature file without CERT
+pkcs7_data_without_cert_signed.der: $(pkcs7_test_file) $(pkcs7_test_cert_1)
+ $(OPENSSL) smime -sign -binary -in pkcs7_data.bin -out $@ -md sha256 -signer pkcs7-rsa-sha256-1.pem -nocerts -noattr -outform DER -out $@
+all_final += pkcs7_data_without_cert_signed.der
+
+# pkcs7 signature file with multiple signers
+pkcs7_data_multiple_signed.der: $(pkcs7_test_file) $(pkcs7_test_cert_1) $(pkcs7_test_cert_2)
+ $(OPENSSL) smime -sign -binary -in pkcs7_data.bin -out $@ -md sha256 -signer pkcs7-rsa-sha256-1.pem -signer pkcs7-rsa-sha256-2.pem -nocerts -noattr -outform DER -out $@
+all_final += pkcs7_data_multiple_signed.der
+
+# pkcs7 signature file with multiple certificates
+pkcs7_data_multiple_certs_signed.der: $(pkcs7_test_file) $(pkcs7_test_cert_1) $(pkcs7_test_cert_2)
+ $(OPENSSL) smime -sign -binary -in pkcs7_data.bin -out $@ -md sha256 -signer pkcs7-rsa-sha256-1.pem -signer pkcs7-rsa-sha256-2.pem -noattr -outform DER -out $@
+all_final += pkcs7_data_multiple_certs_signed.der
+
+# pkcs7 signature file with corrupted CERT
+pkcs7_data_signed_badcert.der: pkcs7_data_cert_signed_sha256.der
+ cp pkcs7_data_cert_signed_sha256.der $@
+ echo -en '\xa1' | dd of=$@ bs=1 seek=547 conv=notrunc
+all_final += pkcs7_data_signed_badcert.der
+
+# pkcs7 signature file with corrupted signer info
+pkcs7_data_signed_badsigner.der: pkcs7_data_cert_signed_sha256.der
+ cp pkcs7_data_cert_signed_sha256.der $@
+ echo -en '\xa1' | dd of=$@ bs=1 seek=918 conv=notrunc
+all_final += pkcs7_data_signed_badsigner.der
+
+# pkcs7 file with version 2
+pkcs7_data_cert_signed_v2.der: pkcs7_data_cert_signed_sha256.der
+ cp pkcs7_data_cert_signed_sha256.der $@
+ echo -en '\x02' | dd of=$@ bs=1 seek=25 conv=notrunc
+all_final += pkcs7_data_cert_signed_v2.der
+
+pkcs7_data_cert_encrypted.der: $(pkcs7_test_file) $(pkcs7_test_cert_1)
+ $(OPENSSL) smime -encrypt -aes256 -in pkcs7_data.bin -binary -outform DER -out $@ pkcs7-rsa-sha256-1.crt
+all_final += pkcs7_data_cert_encrypted.der
+
+## Negative tests
+# For some interesting sizes, what happens if we make them off-by-one?
+pkcs7_signerInfo_issuer_invalid_size.der: pkcs7_data_cert_signed_sha256.der
+ cp $< $@
+ echo -en '\x35' | dd of=$@ seek=919 bs=1 conv=notrunc
+all_final += pkcs7_signerInfo_issuer_invalid_size.der
+
+pkcs7_signerInfo_serial_invalid_size.der: pkcs7_data_cert_signed_sha256.der
+ cp $< $@
+ echo -en '\x15' | dd of=$@ seek=973 bs=1 conv=notrunc
+all_final += pkcs7_signerInfo_serial_invalid_size.der
+
+# pkcs7 signature file just with signed data
+pkcs7_data_cert_signeddata_sha256.der: pkcs7_data_cert_signed_sha256.der
+ dd if=pkcs7_data_cert_signed_sha256.der of=$@ skip=19 bs=1
+all_final += pkcs7_data_cert_signeddata_sha256.der
+
################################################################
#### Diffie-Hellman parameters
################################################################
diff --git a/tests/data_files/pkcs7-rsa-sha256-1.crt b/tests/data_files/pkcs7-rsa-sha256-1.crt
new file mode 100644
index 0000000..9e461cd
--- /dev/null
+++ b/tests/data_files/pkcs7-rsa-sha256-1.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDSTCCAjGgAwIBAgIUe97d0kRM0c3+XEGoECyJt98ubL8wDQYJKoZIhvcNAQEL
+BQAwNDELMAkGA1UEBhMCTkwxDjAMBgNVBAoMBVBLQ1M3MRUwEwYDVQQDDAxQS0NT
+NyBDZXJ0IDEwHhcNMjIxMDI4MTYxMDU2WhcNMjMxMDI4MTYxMDU2WjA0MQswCQYD
+VQQGEwJOTDEOMAwGA1UECgwFUEtDUzcxFTATBgNVBAMMDFBLQ1M3IENlcnQgMTCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMi2z2mJnNHw67TKZFwF5w4N
+Lv7dzGHQicvVFaOaNXm5I0O2HsdQBg+07TeHYzJADkJfHTdsfnXClzMU7fS7MMj4
+3QO5/P+VWiRdSRN61uYAVsrBlVKoZdUhhxh8wELJxJ4+OpwXpTS0U82rwMsRO09j
+9bMXS57pkCsZENEUlqJ5p0Mmrc/uEL/Z5+uvuzd76bY5WRZdE91XURccra08HTra
+xovIAR1htUz2AXi+NoOaiayRq0GePKN9a6iB0lUYxNtovKb3yDYC9pmoaxf7Hnc7
+y+dLuTpJslGuhkKLV0Dhhoux1vq54ocS6Y7DGa2Pyk1zAQxLCcS4BFiWHnzwg1MC
+AwEAAaNTMFEwHQYDVR0OBBYEFIru5ZR8xnxd1RWnbip+zTHuUv3IMB8GA1UdIwQY
+MBaAFIru5ZR8xnxd1RWnbip+zTHuUv3IMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
+hvcNAQELBQADggEBAIIda5jNRX3r0rCBrKJ+vs1Pk6zIKEQ7Oeq/+p+k6eRUO0b8
+wx4rW0gXeQPeppaaxKLMZXBlA5DxsI1DpML5dcfti/M1bHIYOAISRRqPEd5GVTy8
+1ltCVN249mg06yHdoqjzO1geFIRVesoblO6JMd3xYDe3pxcTIakZNq/Cf/zjld51
+1fcMuLWu4F/1BwiNZa8eQ5Zs1Cy+b3+s+NrgVd2CIrFpZSFyP4EkUXhZXJha6Rf9
+SzmYdz4al7e9EAhURvQlm8wJpFSSkoLBuJtx7Vh6d14KPUU2NB9F2ulp6AbJb+/H
+EGd3bAK6IhIrkZmxTAwowESHUJBwuX890tbZcnM=
+-----END CERTIFICATE-----
diff --git a/tests/data_files/pkcs7-rsa-sha256-1.der b/tests/data_files/pkcs7-rsa-sha256-1.der
new file mode 100644
index 0000000..0d799ea
--- /dev/null
+++ b/tests/data_files/pkcs7-rsa-sha256-1.der
Binary files differ
diff --git a/tests/data_files/pkcs7-rsa-sha256-1.key b/tests/data_files/pkcs7-rsa-sha256-1.key
new file mode 100644
index 0000000..e31159d
--- /dev/null
+++ b/tests/data_files/pkcs7-rsa-sha256-1.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDIts9piZzR8Ou0
+ymRcBecODS7+3cxh0InL1RWjmjV5uSNDth7HUAYPtO03h2MyQA5CXx03bH51wpcz
+FO30uzDI+N0Dufz/lVokXUkTetbmAFbKwZVSqGXVIYcYfMBCycSePjqcF6U0tFPN
+q8DLETtPY/WzF0ue6ZArGRDRFJaieadDJq3P7hC/2efrr7s3e+m2OVkWXRPdV1EX
+HK2tPB062saLyAEdYbVM9gF4vjaDmomskatBnjyjfWuogdJVGMTbaLym98g2AvaZ
+qGsX+x53O8vnS7k6SbJRroZCi1dA4YaLsdb6ueKHEumOwxmtj8pNcwEMSwnEuARY
+lh588INTAgMBAAECggEBAIg+P1B+TurbRMQ11iX5A7wwCsSKPh/vdHneLJAfL0lu
++JcP2piko1iqEZPt3NHRVVyMP8LNbJH3Ardz74p+PkFNXIkZCLlc4hFpGR+V9KWv
+eTqsaPXwxR8FYTSoCcHMQCDCUPp/um6qMXCcs4OkMMRVMATfPT+jf28h1p52AUJL
+aAoBJfn7gP3WiB0FWq0bRZgSZzNYowE/MhGAQ+DuBGTSASSK3YJcxE94044fBVE8
+EqYKrxoY/x56li5cZ0v9kaURCrvhqCeq2+U5kIkgtvp2l6wF0Mm1du3BLxo2LQEI
+Y2j+6BFEV74Mtv48GTwrZcyit787zyo9vVGcviSD5VECgYEA/mgLc5KfF/cQLmM/
+20T4k0edvktkRIJHFUBphowt5Hb0a0wM5C1VM4z3yN3b9ikQK+ZaQXETdPATBXIe
+LntX1D1xtbMxdcAfd1FSq8QxAuaPknJZBgtzlpCsx3ZvMnNuzKZN/TU8kR1biwPE
+9HaeEG3bouUu+CI/l/DqrBbQRacCgYEAyfiqsLWGhXQ7e3pLk47PDYlMOsjDWPjs
+SGcatH1/lIMWyZue4W2IUcFMbpbjA6QWibo3VnOavIRSTn97JNUWYvgc5MmaQ7iX
+Iss4m3vJ1LIqx30iUgw3EfDoWdpufEEYssZ/VxJPs3sdmZGALgd3CaqxHJuhuS+U
+eVhWzD6LonUCgYBRCbt8GRxsedrBrAPPSO0VnR52W3WZDRavglEa9tQ3jlzVQOhq
+VrZpMWJMrb8/bl0kXsApUGeuPDsS5QMQM2IKzXfHNUlwBL8BNvpqlJg4IFFjiOEq
+t8MeFv+ymdtZ6sNElUUKf0bHwt5CLfUzGgXHnfb0sKSBjgdL0wYtwyacyQKBgQDJ
+NcyG4zEy/srLhtiIFnu8Fo40+hFzL/nlX6JBMc3KHJa1Hy43krF+ET6d5gAffndd
+moDKxbzgFksRHPuHhCobSucuHpJq6RjYdvDcJYS7OwxXVRi9+KFcZE52RaBQdWGv
+qQTvr7RrMDoa5dN3B8TVgpGT2JBTN02JXjKKo7zkiQKBgCZwKDiXl7qsGidvlFZc
+4CEtFsCgnNgdRTzsTL/Pr8q9CBK3BhjZjNzQALF1iGFDC1FdFYFOwI1E3j+MRHJB
+rQMF8zbmmlZ6SC5QtqatCSCCKUyrUjD5J+4UfJqWFjiBBdwz+5VJojHw1yijEwl4
+LrS/V2yBrDJVczQQM4psonLF
+-----END PRIVATE KEY-----
diff --git a/tests/data_files/pkcs7-rsa-sha256-1.pem b/tests/data_files/pkcs7-rsa-sha256-1.pem
new file mode 100644
index 0000000..3795b71
--- /dev/null
+++ b/tests/data_files/pkcs7-rsa-sha256-1.pem
@@ -0,0 +1,48 @@
+-----BEGIN CERTIFICATE-----
+MIIDSTCCAjGgAwIBAgIUe97d0kRM0c3+XEGoECyJt98ubL8wDQYJKoZIhvcNAQEL
+BQAwNDELMAkGA1UEBhMCTkwxDjAMBgNVBAoMBVBLQ1M3MRUwEwYDVQQDDAxQS0NT
+NyBDZXJ0IDEwHhcNMjIxMDI4MTYxMDU2WhcNMjMxMDI4MTYxMDU2WjA0MQswCQYD
+VQQGEwJOTDEOMAwGA1UECgwFUEtDUzcxFTATBgNVBAMMDFBLQ1M3IENlcnQgMTCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMi2z2mJnNHw67TKZFwF5w4N
+Lv7dzGHQicvVFaOaNXm5I0O2HsdQBg+07TeHYzJADkJfHTdsfnXClzMU7fS7MMj4
+3QO5/P+VWiRdSRN61uYAVsrBlVKoZdUhhxh8wELJxJ4+OpwXpTS0U82rwMsRO09j
+9bMXS57pkCsZENEUlqJ5p0Mmrc/uEL/Z5+uvuzd76bY5WRZdE91XURccra08HTra
+xovIAR1htUz2AXi+NoOaiayRq0GePKN9a6iB0lUYxNtovKb3yDYC9pmoaxf7Hnc7
+y+dLuTpJslGuhkKLV0Dhhoux1vq54ocS6Y7DGa2Pyk1zAQxLCcS4BFiWHnzwg1MC
+AwEAAaNTMFEwHQYDVR0OBBYEFIru5ZR8xnxd1RWnbip+zTHuUv3IMB8GA1UdIwQY
+MBaAFIru5ZR8xnxd1RWnbip+zTHuUv3IMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
+hvcNAQELBQADggEBAIIda5jNRX3r0rCBrKJ+vs1Pk6zIKEQ7Oeq/+p+k6eRUO0b8
+wx4rW0gXeQPeppaaxKLMZXBlA5DxsI1DpML5dcfti/M1bHIYOAISRRqPEd5GVTy8
+1ltCVN249mg06yHdoqjzO1geFIRVesoblO6JMd3xYDe3pxcTIakZNq/Cf/zjld51
+1fcMuLWu4F/1BwiNZa8eQ5Zs1Cy+b3+s+NrgVd2CIrFpZSFyP4EkUXhZXJha6Rf9
+SzmYdz4al7e9EAhURvQlm8wJpFSSkoLBuJtx7Vh6d14KPUU2NB9F2ulp6AbJb+/H
+EGd3bAK6IhIrkZmxTAwowESHUJBwuX890tbZcnM=
+-----END CERTIFICATE-----
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDIts9piZzR8Ou0
+ymRcBecODS7+3cxh0InL1RWjmjV5uSNDth7HUAYPtO03h2MyQA5CXx03bH51wpcz
+FO30uzDI+N0Dufz/lVokXUkTetbmAFbKwZVSqGXVIYcYfMBCycSePjqcF6U0tFPN
+q8DLETtPY/WzF0ue6ZArGRDRFJaieadDJq3P7hC/2efrr7s3e+m2OVkWXRPdV1EX
+HK2tPB062saLyAEdYbVM9gF4vjaDmomskatBnjyjfWuogdJVGMTbaLym98g2AvaZ
+qGsX+x53O8vnS7k6SbJRroZCi1dA4YaLsdb6ueKHEumOwxmtj8pNcwEMSwnEuARY
+lh588INTAgMBAAECggEBAIg+P1B+TurbRMQ11iX5A7wwCsSKPh/vdHneLJAfL0lu
++JcP2piko1iqEZPt3NHRVVyMP8LNbJH3Ardz74p+PkFNXIkZCLlc4hFpGR+V9KWv
+eTqsaPXwxR8FYTSoCcHMQCDCUPp/um6qMXCcs4OkMMRVMATfPT+jf28h1p52AUJL
+aAoBJfn7gP3WiB0FWq0bRZgSZzNYowE/MhGAQ+DuBGTSASSK3YJcxE94044fBVE8
+EqYKrxoY/x56li5cZ0v9kaURCrvhqCeq2+U5kIkgtvp2l6wF0Mm1du3BLxo2LQEI
+Y2j+6BFEV74Mtv48GTwrZcyit787zyo9vVGcviSD5VECgYEA/mgLc5KfF/cQLmM/
+20T4k0edvktkRIJHFUBphowt5Hb0a0wM5C1VM4z3yN3b9ikQK+ZaQXETdPATBXIe
+LntX1D1xtbMxdcAfd1FSq8QxAuaPknJZBgtzlpCsx3ZvMnNuzKZN/TU8kR1biwPE
+9HaeEG3bouUu+CI/l/DqrBbQRacCgYEAyfiqsLWGhXQ7e3pLk47PDYlMOsjDWPjs
+SGcatH1/lIMWyZue4W2IUcFMbpbjA6QWibo3VnOavIRSTn97JNUWYvgc5MmaQ7iX
+Iss4m3vJ1LIqx30iUgw3EfDoWdpufEEYssZ/VxJPs3sdmZGALgd3CaqxHJuhuS+U
+eVhWzD6LonUCgYBRCbt8GRxsedrBrAPPSO0VnR52W3WZDRavglEa9tQ3jlzVQOhq
+VrZpMWJMrb8/bl0kXsApUGeuPDsS5QMQM2IKzXfHNUlwBL8BNvpqlJg4IFFjiOEq
+t8MeFv+ymdtZ6sNElUUKf0bHwt5CLfUzGgXHnfb0sKSBjgdL0wYtwyacyQKBgQDJ
+NcyG4zEy/srLhtiIFnu8Fo40+hFzL/nlX6JBMc3KHJa1Hy43krF+ET6d5gAffndd
+moDKxbzgFksRHPuHhCobSucuHpJq6RjYdvDcJYS7OwxXVRi9+KFcZE52RaBQdWGv
+qQTvr7RrMDoa5dN3B8TVgpGT2JBTN02JXjKKo7zkiQKBgCZwKDiXl7qsGidvlFZc
+4CEtFsCgnNgdRTzsTL/Pr8q9CBK3BhjZjNzQALF1iGFDC1FdFYFOwI1E3j+MRHJB
+rQMF8zbmmlZ6SC5QtqatCSCCKUyrUjD5J+4UfJqWFjiBBdwz+5VJojHw1yijEwl4
+LrS/V2yBrDJVczQQM4psonLF
+-----END PRIVATE KEY-----
diff --git a/tests/data_files/pkcs7-rsa-sha256-2.crt b/tests/data_files/pkcs7-rsa-sha256-2.crt
new file mode 100644
index 0000000..a0df7d9
--- /dev/null
+++ b/tests/data_files/pkcs7-rsa-sha256-2.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDSTCCAjGgAwIBAgIUVk1VQCWvWZ4ycHmycg7wDfN8+3wwDQYJKoZIhvcNAQEL
+BQAwNDELMAkGA1UEBhMCTkwxDjAMBgNVBAoMBVBLQ1M3MRUwEwYDVQQDDAxQS0NT
+NyBDZXJ0IDIwHhcNMjIxMDI4MTYxMDU2WhcNMjMxMDI4MTYxMDU2WjA0MQswCQYD
+VQQGEwJOTDEOMAwGA1UECgwFUEtDUzcxFTATBgNVBAMMDFBLQ1M3IENlcnQgMjCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMmVNZZ0/qcT+h/lVNO+gP65
+lERTTudQ15h8QTLjaKhx5SSTLnuUhD0jLbR+ng8PMqdJ8ePkZEh1+7mi9MHzID4Y
+c47jH8M+Jc/JdBr6cSjbFd23QHESUjKKmV1IjSHc6Llbxe962z4gEXYjJAMkfr6B
+g1iecK3AlnEI4F0BsQfC5dgA4Qce2okvcTuhYgvHtLZ+UN4ca50Kw0o4u5FYdl89
+KDCE4zNp8MaaxGC83xcM4A9XqjHyZ7a2wvACTlmLQ2q/E+RN/8THEel4Y+yv82Uj
+j2LqqEaA06dvSdOPdaGz9jUZauqBw7TcuGGVzrrsZ0g/sHXKng9TppehAV/HrJUC
+AwEAAaNTMFEwHQYDVR0OBBYEFI5FVrtfLwPXRERcyVX6qBVvfoduMB8GA1UdIwQY
+MBaAFI5FVrtfLwPXRERcyVX6qBVvfoduMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
+hvcNAQELBQADggEBAKRl0wgREe6eAduJSV5fs+Ec0s2qs2lHQqt/0JGEIbZBBtka
+q1UH9CIMMAd6Kb0kh5GlJT2shg/EAYWoitMwntkeRYTln2k2/B5jux+U5Ph4HyC+
+ad2GqmsoXWDru79rltT7Pv1hS1ofJyQ4Jv88vQA/SuIIRGdTC24VAVgg00JxvDRB
+xeqsQ9Pld4ebg4VvqsInnSpmKCcxfWxFhJk/Ax8bK/tV/GnrPiwsvry1j9nZyebS
+IyI01/6DwJS2ZhFnsLGyPHFOAFNtomjIdQ6gf2L1wq0qiGOKj/K9IzFNCpCz82a+
+gMgqFzCT5TCZC16kUG2NA2pXAx9O4uppKjRk97U=
+-----END CERTIFICATE-----
diff --git a/tests/data_files/pkcs7-rsa-sha256-2.der b/tests/data_files/pkcs7-rsa-sha256-2.der
new file mode 100644
index 0000000..fc7a3ea
--- /dev/null
+++ b/tests/data_files/pkcs7-rsa-sha256-2.der
Binary files differ
diff --git a/tests/data_files/pkcs7-rsa-sha256-2.key b/tests/data_files/pkcs7-rsa-sha256-2.key
new file mode 100644
index 0000000..659c015
--- /dev/null
+++ b/tests/data_files/pkcs7-rsa-sha256-2.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDJlTWWdP6nE/of
+5VTTvoD+uZREU07nUNeYfEEy42ioceUkky57lIQ9Iy20fp4PDzKnSfHj5GRIdfu5
+ovTB8yA+GHOO4x/DPiXPyXQa+nEo2xXdt0BxElIyipldSI0h3Oi5W8Xvets+IBF2
+IyQDJH6+gYNYnnCtwJZxCOBdAbEHwuXYAOEHHtqJL3E7oWILx7S2flDeHGudCsNK
+OLuRWHZfPSgwhOMzafDGmsRgvN8XDOAPV6ox8me2tsLwAk5Zi0NqvxPkTf/ExxHp
+eGPsr/NlI49i6qhGgNOnb0nTj3Whs/Y1GWrqgcO03Lhhlc667GdIP7B1yp4PU6aX
+oQFfx6yVAgMBAAECggEBAMVHm3w134qQCHfyroPTqtaftDTx+wRyn6yB3iT5XdGM
+NZ8H07Pp80kKBo7gY7uFOiNyQKKxQFuR69sPWc3+LI3YzC8IpGslhUfHdjN46gn7
+73hfAVgnf/4qmlEq0cRUOAY/hIUMjUhNhglB9tqEeu3iPjMaTFgfZJwW/czH/QMD
+w4zj5XoLgwRkqVvUceu/dBgV8KP5DpON+q8wpfWtjunv7rg5Nc3BVBrpb5SadJ7T
+i5TsS+pZQyp+mTvyCI3A1hkr2Vw5tULWO8SPhuEQkdtC/CL+luCUO7L16lU6KhFB
+qP5Fduik5skyLCVvAMUkjKcrC22k0gkhOHvfmMhjaAECgYEA68+hAQIiV9ErZGk9
+ZLu+VJHBSPmEQCkUcbviwzoRo8YSyka12TZERy+NJcvmD9deNgFbp8GyZf01XJWH
+slSYt6LyInrJrTpv+3q2Vl5GQp0f+39i7MHnwGGKbWsDbSAm+L9yKTJzYJz1O5fo
+in06AiyyGPwnXd1cm5bTXVX+dQECgYEA2tdi6DXF8awE23pv4HphPBhXS5hmYP/D
+NC7CtP8wQsxjPdiIxkBFFVEaFCC2njq1VhTyJb5noJM4kOIwcoaQ/zgyyxQa0u7w
++CqvAh1WwG+sT/B7vivrtDmmYeyGQapFo5DRIz+MflKAhzDhtnEyT9vLuCdn8J95
+0YvxZJ9+k5UCgYEAh+e7SER9nJUt6AoLWyIlGMKEXlWIFh5W7RG3KIMwJW6D59aG
++fAfu9M5Cx6PsnOSlZeExpOJCOS9O2Xmti2xcqzT1nFkCJWUcqCPtAlTfxLlmuIZ
+FpDOy36r9FHnwJ32OAjGd93ex0DOyZDMcfyoURaHcoTo/10UAYwUt0dXhwECgYAI
+xad2TWmA1XdgYNkJM36gTQ16v0IjUz084z70yGHj25OC0CIzaDIct6KG+gS39Px9
+1dsa/jXjLuOOkzKD9LbtNBB9KXIl0GQiXnujZw+qKQ/MKISdS99n2wO7WyLKkQu3
+kb+AXTTBf4cdZC04BfORVesll5bIA2x7pNNpSCdnvQKBgG7VXYcPlIV7iAyi2xFa
+uN1jccu/AK7xA0G1jz2SHNlpet74LmWR8XsTujJeo8WG1IRFxSky4h/pAP0XWIFO
+0LPK7eeDtnFq6y1/DXpI+/9BWX5T/8+4Yk93p37YrBVWKfd21dhrAklQs11m3rlQ
+Qn6c/zyvMKSyrCVxo5pTd5Il
+-----END PRIVATE KEY-----
diff --git a/tests/data_files/pkcs7-rsa-sha256-2.pem b/tests/data_files/pkcs7-rsa-sha256-2.pem
new file mode 100644
index 0000000..b11a00a
--- /dev/null
+++ b/tests/data_files/pkcs7-rsa-sha256-2.pem
@@ -0,0 +1,48 @@
+-----BEGIN CERTIFICATE-----
+MIIDSTCCAjGgAwIBAgIUVk1VQCWvWZ4ycHmycg7wDfN8+3wwDQYJKoZIhvcNAQEL
+BQAwNDELMAkGA1UEBhMCTkwxDjAMBgNVBAoMBVBLQ1M3MRUwEwYDVQQDDAxQS0NT
+NyBDZXJ0IDIwHhcNMjIxMDI4MTYxMDU2WhcNMjMxMDI4MTYxMDU2WjA0MQswCQYD
+VQQGEwJOTDEOMAwGA1UECgwFUEtDUzcxFTATBgNVBAMMDFBLQ1M3IENlcnQgMjCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMmVNZZ0/qcT+h/lVNO+gP65
+lERTTudQ15h8QTLjaKhx5SSTLnuUhD0jLbR+ng8PMqdJ8ePkZEh1+7mi9MHzID4Y
+c47jH8M+Jc/JdBr6cSjbFd23QHESUjKKmV1IjSHc6Llbxe962z4gEXYjJAMkfr6B
+g1iecK3AlnEI4F0BsQfC5dgA4Qce2okvcTuhYgvHtLZ+UN4ca50Kw0o4u5FYdl89
+KDCE4zNp8MaaxGC83xcM4A9XqjHyZ7a2wvACTlmLQ2q/E+RN/8THEel4Y+yv82Uj
+j2LqqEaA06dvSdOPdaGz9jUZauqBw7TcuGGVzrrsZ0g/sHXKng9TppehAV/HrJUC
+AwEAAaNTMFEwHQYDVR0OBBYEFI5FVrtfLwPXRERcyVX6qBVvfoduMB8GA1UdIwQY
+MBaAFI5FVrtfLwPXRERcyVX6qBVvfoduMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
+hvcNAQELBQADggEBAKRl0wgREe6eAduJSV5fs+Ec0s2qs2lHQqt/0JGEIbZBBtka
+q1UH9CIMMAd6Kb0kh5GlJT2shg/EAYWoitMwntkeRYTln2k2/B5jux+U5Ph4HyC+
+ad2GqmsoXWDru79rltT7Pv1hS1ofJyQ4Jv88vQA/SuIIRGdTC24VAVgg00JxvDRB
+xeqsQ9Pld4ebg4VvqsInnSpmKCcxfWxFhJk/Ax8bK/tV/GnrPiwsvry1j9nZyebS
+IyI01/6DwJS2ZhFnsLGyPHFOAFNtomjIdQ6gf2L1wq0qiGOKj/K9IzFNCpCz82a+
+gMgqFzCT5TCZC16kUG2NA2pXAx9O4uppKjRk97U=
+-----END CERTIFICATE-----
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDJlTWWdP6nE/of
+5VTTvoD+uZREU07nUNeYfEEy42ioceUkky57lIQ9Iy20fp4PDzKnSfHj5GRIdfu5
+ovTB8yA+GHOO4x/DPiXPyXQa+nEo2xXdt0BxElIyipldSI0h3Oi5W8Xvets+IBF2
+IyQDJH6+gYNYnnCtwJZxCOBdAbEHwuXYAOEHHtqJL3E7oWILx7S2flDeHGudCsNK
+OLuRWHZfPSgwhOMzafDGmsRgvN8XDOAPV6ox8me2tsLwAk5Zi0NqvxPkTf/ExxHp
+eGPsr/NlI49i6qhGgNOnb0nTj3Whs/Y1GWrqgcO03Lhhlc667GdIP7B1yp4PU6aX
+oQFfx6yVAgMBAAECggEBAMVHm3w134qQCHfyroPTqtaftDTx+wRyn6yB3iT5XdGM
+NZ8H07Pp80kKBo7gY7uFOiNyQKKxQFuR69sPWc3+LI3YzC8IpGslhUfHdjN46gn7
+73hfAVgnf/4qmlEq0cRUOAY/hIUMjUhNhglB9tqEeu3iPjMaTFgfZJwW/czH/QMD
+w4zj5XoLgwRkqVvUceu/dBgV8KP5DpON+q8wpfWtjunv7rg5Nc3BVBrpb5SadJ7T
+i5TsS+pZQyp+mTvyCI3A1hkr2Vw5tULWO8SPhuEQkdtC/CL+luCUO7L16lU6KhFB
+qP5Fduik5skyLCVvAMUkjKcrC22k0gkhOHvfmMhjaAECgYEA68+hAQIiV9ErZGk9
+ZLu+VJHBSPmEQCkUcbviwzoRo8YSyka12TZERy+NJcvmD9deNgFbp8GyZf01XJWH
+slSYt6LyInrJrTpv+3q2Vl5GQp0f+39i7MHnwGGKbWsDbSAm+L9yKTJzYJz1O5fo
+in06AiyyGPwnXd1cm5bTXVX+dQECgYEA2tdi6DXF8awE23pv4HphPBhXS5hmYP/D
+NC7CtP8wQsxjPdiIxkBFFVEaFCC2njq1VhTyJb5noJM4kOIwcoaQ/zgyyxQa0u7w
++CqvAh1WwG+sT/B7vivrtDmmYeyGQapFo5DRIz+MflKAhzDhtnEyT9vLuCdn8J95
+0YvxZJ9+k5UCgYEAh+e7SER9nJUt6AoLWyIlGMKEXlWIFh5W7RG3KIMwJW6D59aG
++fAfu9M5Cx6PsnOSlZeExpOJCOS9O2Xmti2xcqzT1nFkCJWUcqCPtAlTfxLlmuIZ
+FpDOy36r9FHnwJ32OAjGd93ex0DOyZDMcfyoURaHcoTo/10UAYwUt0dXhwECgYAI
+xad2TWmA1XdgYNkJM36gTQ16v0IjUz084z70yGHj25OC0CIzaDIct6KG+gS39Px9
+1dsa/jXjLuOOkzKD9LbtNBB9KXIl0GQiXnujZw+qKQ/MKISdS99n2wO7WyLKkQu3
+kb+AXTTBf4cdZC04BfORVesll5bIA2x7pNNpSCdnvQKBgG7VXYcPlIV7iAyi2xFa
+uN1jccu/AK7xA0G1jz2SHNlpet74LmWR8XsTujJeo8WG1IRFxSky4h/pAP0XWIFO
+0LPK7eeDtnFq6y1/DXpI+/9BWX5T/8+4Yk93p37YrBVWKfd21dhrAklQs11m3rlQ
+Qn6c/zyvMKSyrCVxo5pTd5Il
+-----END PRIVATE KEY-----
diff --git a/tests/data_files/pkcs7_data.bin b/tests/data_files/pkcs7_data.bin
new file mode 100644
index 0000000..40ee264
--- /dev/null
+++ b/tests/data_files/pkcs7_data.bin
@@ -0,0 +1 @@
+Hello
diff --git a/tests/data_files/pkcs7_data_1.bin b/tests/data_files/pkcs7_data_1.bin
new file mode 100644
index 0000000..78c6bae
--- /dev/null
+++ b/tests/data_files/pkcs7_data_1.bin
@@ -0,0 +1 @@
+2
diff --git a/tests/data_files/pkcs7_data_cert_encrypted.der b/tests/data_files/pkcs7_data_cert_encrypted.der
new file mode 100644
index 0000000..b7b1c83
--- /dev/null
+++ b/tests/data_files/pkcs7_data_cert_encrypted.der
Binary files differ
diff --git a/tests/data_files/pkcs7_data_cert_signed_sha1.der b/tests/data_files/pkcs7_data_cert_signed_sha1.der
new file mode 100644
index 0000000..fb1deb0
--- /dev/null
+++ b/tests/data_files/pkcs7_data_cert_signed_sha1.der
Binary files differ
diff --git a/tests/data_files/pkcs7_data_cert_signed_sha256.der b/tests/data_files/pkcs7_data_cert_signed_sha256.der
new file mode 100644
index 0000000..8dc2f4c
--- /dev/null
+++ b/tests/data_files/pkcs7_data_cert_signed_sha256.der
Binary files differ
diff --git a/tests/data_files/pkcs7_data_cert_signed_sha512.der b/tests/data_files/pkcs7_data_cert_signed_sha512.der
new file mode 100644
index 0000000..a4aa587
--- /dev/null
+++ b/tests/data_files/pkcs7_data_cert_signed_sha512.der
Binary files differ
diff --git a/tests/data_files/pkcs7_data_cert_signed_v2.der b/tests/data_files/pkcs7_data_cert_signed_v2.der
new file mode 100644
index 0000000..4f4cb04
--- /dev/null
+++ b/tests/data_files/pkcs7_data_cert_signed_v2.der
Binary files differ
diff --git a/tests/data_files/pkcs7_data_cert_signeddata_sha256.der b/tests/data_files/pkcs7_data_cert_signeddata_sha256.der
new file mode 100644
index 0000000..cb7d751
--- /dev/null
+++ b/tests/data_files/pkcs7_data_cert_signeddata_sha256.der
Binary files differ
diff --git a/tests/data_files/pkcs7_data_multiple_certs_signed.der b/tests/data_files/pkcs7_data_multiple_certs_signed.der
new file mode 100644
index 0000000..4a237e9
--- /dev/null
+++ b/tests/data_files/pkcs7_data_multiple_certs_signed.der
Binary files differ
diff --git a/tests/data_files/pkcs7_data_multiple_signed.der b/tests/data_files/pkcs7_data_multiple_signed.der
new file mode 100644
index 0000000..095b80c
--- /dev/null
+++ b/tests/data_files/pkcs7_data_multiple_signed.der
Binary files differ
diff --git a/tests/data_files/pkcs7_data_signed_badcert.der b/tests/data_files/pkcs7_data_signed_badcert.der
new file mode 100644
index 0000000..ed00f65
--- /dev/null
+++ b/tests/data_files/pkcs7_data_signed_badcert.der
Binary files differ
diff --git a/tests/data_files/pkcs7_data_signed_badsigner.der b/tests/data_files/pkcs7_data_signed_badsigner.der
new file mode 100644
index 0000000..aa5447c
--- /dev/null
+++ b/tests/data_files/pkcs7_data_signed_badsigner.der
Binary files differ
diff --git a/tests/data_files/pkcs7_data_without_cert_signed.der b/tests/data_files/pkcs7_data_without_cert_signed.der
new file mode 100644
index 0000000..b47fe92
--- /dev/null
+++ b/tests/data_files/pkcs7_data_without_cert_signed.der
Binary files differ
diff --git a/tests/data_files/pkcs7_signerInfo_issuer_invalid_size.der b/tests/data_files/pkcs7_signerInfo_issuer_invalid_size.der
new file mode 100644
index 0000000..898ca67
--- /dev/null
+++ b/tests/data_files/pkcs7_signerInfo_issuer_invalid_size.der
Binary files differ
diff --git a/tests/data_files/pkcs7_signerInfo_serial_invalid_size.der b/tests/data_files/pkcs7_signerInfo_serial_invalid_size.der
new file mode 100644
index 0000000..f4b4e38
--- /dev/null
+++ b/tests/data_files/pkcs7_signerInfo_serial_invalid_size.der
Binary files differ
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 9295c9d..716495e 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -1217,6 +1217,7 @@
# Direct dependencies
scripts/config.py unset MBEDTLS_HKDF_C
scripts/config.py unset MBEDTLS_HMAC_DRBG_C
+ scripts/config.py unset MBEDTLS_PKCS7_C
# Indirect dependencies
scripts/config.py unset MBEDTLS_ECDSA_DETERMINISTIC
make
@@ -2104,6 +2105,7 @@
scripts/config.py unset MBEDTLS_MD_C
scripts/config.py unset MBEDTLS_HKDF_C # has independent PSA implementation
scripts/config.py unset MBEDTLS_HMAC_DRBG_C
+ scripts/config.py unset MBEDTLS_PKCS7_C
scripts/config.py unset MBEDTLS_ECDSA_DETERMINISTIC
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_DETERMINISTIC_ECDSA
diff --git a/tests/scripts/check_files.py b/tests/scripts/check_files.py
index 5c18702..42f2e82 100755
--- a/tests/scripts/check_files.py
+++ b/tests/scripts/check_files.py
@@ -122,6 +122,7 @@
r'tests/data_files/.*\.req\.[^/]+\Z',
r'tests/data_files/.*malformed[^/]+\Z',
r'tests/data_files/format_pkcs12\.fmt\Z',
+ r'tests/data_files/pkcs7_data.*\.bin\Z',
]
BINARY_FILE_PATH_RE = re.compile('|'.join(BINARY_FILE_PATH_RE_LIST))
diff --git a/tests/suites/test_suite_pkcs7.data b/tests/suites/test_suite_pkcs7.data
new file mode 100644
index 0000000..4f81b6f
--- /dev/null
+++ b/tests/suites/test_suite_pkcs7.data
@@ -0,0 +1,75 @@
+PKCS7 Signed Data Parse Pass SHA256 #1
+depends_on:MBEDTLS_SHA256_C:MBEDTLS_RSA_C
+pkcs7_parse:"data_files/pkcs7_data_cert_signed_sha256.der":MBEDTLS_PKCS7_SIGNED_DATA
+
+PKCS7 Signed Data Parse Pass SHA1 #2
+depends_on:MBEDTLS_SHA1_C:MBEDTLS_SHA256_C:MBEDTLS_RSA_C
+pkcs7_parse:"data_files/pkcs7_data_cert_signed_sha1.der":MBEDTLS_PKCS7_SIGNED_DATA
+
+PKCS7 Signed Data Parse Pass Without CERT #3
+depends_on:MBEDTLS_SHA256_C
+pkcs7_parse:"data_files/pkcs7_data_without_cert_signed.der":MBEDTLS_PKCS7_SIGNED_DATA
+
+PKCS7 Signed Data Parse Fail with multiple certs #4
+depends_on:MBEDTLS_SHA256_C:MBEDTLS_RSA_C
+pkcs7_parse:"data_files/pkcs7_data_multiple_certs_signed.der":MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE
+
+PKCS7 Signed Data Parse Fail with corrupted cert #5
+depends_on:MBEDTLS_SHA256_C:MBEDTLS_RSA_C
+pkcs7_parse:"data_files/pkcs7_data_signed_badcert.der":MBEDTLS_ERR_PKCS7_INVALID_CERT
+
+PKCS7 Signed Data Parse Fail with corrupted signer info #6
+depends_on:MBEDTLS_SHA256_C:MBEDTLS_RSA_C
+pkcs7_parse:"data_files/pkcs7_data_signed_badsigner.der":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO,MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)
+
+PKCS7 Signed Data Parse Fail Version other than 1 #7
+depends_on:MBEDTLS_SHA256_C
+pkcs7_parse:"data_files/pkcs7_data_cert_signed_v2.der":MBEDTLS_ERR_PKCS7_INVALID_VERSION
+
+PKCS7 Signed Data Parse Fail Encrypted Content #8
+depends_on:MBEDTLS_SHA256_C
+pkcs7_parse:"data_files/pkcs7_data_cert_encrypted.der":MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE
+
+PKCS7 Signed Data Verification Pass SHA256 #9
+depends_on:MBEDTLS_SHA256_C
+pkcs7_verify:"data_files/pkcs7_data_cert_signed_sha256.der":"data_files/pkcs7-rsa-sha256-1.der":"data_files/pkcs7_data.bin":0:0
+
+PKCS7 Signed Data Verification Pass SHA256 #9.1
+depends_on:MBEDTLS_SHA256_C
+pkcs7_verify:"data_files/pkcs7_data_cert_signed_sha256.der":"data_files/pkcs7-rsa-sha256-1.der":"data_files/pkcs7_data.bin":MBEDTLS_MD_SHA256:0
+
+PKCS7 Signed Data Verification Pass SHA1 #10
+depends_on:MBEDTLS_SHA1_C:MBEDTLS_SHA256_C
+pkcs7_verify:"data_files/pkcs7_data_cert_signed_sha1.der":"data_files/pkcs7-rsa-sha256-1.der":"data_files/pkcs7_data.bin":0:0
+
+PKCS7 Signed Data Verification Pass SHA512 #11
+depends_on:MBEDTLS_SHA512_C:MBEDTLS_SHA256_C
+pkcs7_verify:"data_files/pkcs7_data_cert_signed_sha512.der":"data_files/pkcs7-rsa-sha256-1.der":"data_files/pkcs7_data.bin":0:0
+
+PKCS7 Signed Data Verification Fail because of different certificate #12
+depends_on:MBEDTLS_SHA256_C
+pkcs7_verify:"data_files/pkcs7_data_cert_signed_sha256.der":"data_files/pkcs7-rsa-sha256-2.der":"data_files/pkcs7_data.bin":0:MBEDTLS_ERR_RSA_VERIFY_FAILED
+
+PKCS7 Signed Data Verification Fail because of different data hash #13
+depends_on:MBEDTLS_SHA256_C
+pkcs7_verify:"data_files/pkcs7_data_cert_signed_sha256.der":"data_files/pkcs7-rsa-sha256-1.der":"data_files/pkcs7_data_1.bin":0:MBEDTLS_ERR_RSA_VERIFY_FAILED
+
+PKCS7 Signed Data Parse Failure Corrupt signerInfo.issuer #15.1
+depends_on:MBEDTLS_SHA256_C
+pkcs7_parse:"data_files/pkcs7_signerInfo_issuer_invalid_size.der":MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO
+
+PKCS7 Signed Data Parse Failure Corrupt signerInfo.serial #15.2
+depends_on:MBEDTLS_SHA256_C
+pkcs7_parse:"data_files/pkcs7_signerInfo_serial_invalid_size.der":MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO
+
+PKCS7 Only Signed Data Parse Pass #15
+depends_on:MBEDTLS_SHA256_C:MBEDTLS_RSA_C
+pkcs7_parse:"data_files/pkcs7_data_cert_signeddata_sha256.der":MBEDTLS_PKCS7_SIGNED_DATA
+
+PKCS7 Signed Data Verify with multiple signers #16
+depends_on:MBEDTLS_SHA256_C
+pkcs7_verify_multiple_signers:"data_files/pkcs7_data_multiple_signed.der":"data_files/pkcs7-rsa-sha256-1.crt":"data_files/pkcs7-rsa-sha256-2.crt":"data_files/pkcs7_data.bin":0:0
+
+PKCS7 Signed Data Hash Verify with multiple signers #17
+depends_on:MBEDTLS_SHA256_C
+pkcs7_verify_multiple_signers:"data_files/pkcs7_data_multiple_signed.der":"data_files/pkcs7-rsa-sha256-1.crt":"data_files/pkcs7-rsa-sha256-2.crt":"data_files/pkcs7_data.bin":MBEDTLS_MD_SHA256:0
diff --git a/tests/suites/test_suite_pkcs7.function b/tests/suites/test_suite_pkcs7.function
new file mode 100644
index 0000000..14a0882
--- /dev/null
+++ b/tests/suites/test_suite_pkcs7.function
@@ -0,0 +1,194 @@
+/* BEGIN_HEADER */
+#include "mbedtls/bignum.h"
+#include "mbedtls/pkcs7.h"
+#include "mbedtls/x509.h"
+#include "mbedtls/x509_crt.h"
+#include "mbedtls/x509_crl.h"
+#include "mbedtls/oid.h"
+#include "sys/types.h"
+#include "sys/stat.h"
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_PKCS7_C:MBEDTLS_RSA_C
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE depends_on:MBEDTLS_FS_IO */
+void pkcs7_parse( char *pkcs7_file, int res_expect )
+{
+ unsigned char *pkcs7_buf = NULL;
+ size_t buflen;
+ int res;
+
+ mbedtls_pkcs7 pkcs7;
+
+ mbedtls_pkcs7_init( &pkcs7 );
+
+ res = mbedtls_pk_load_file( pkcs7_file, &pkcs7_buf, &buflen );
+ TEST_ASSERT( res == 0 );
+
+ res = mbedtls_pkcs7_parse_der( &pkcs7, pkcs7_buf, buflen );
+ TEST_ASSERT( res == res_expect );
+
+exit:
+ mbedtls_free( pkcs7_buf );
+ mbedtls_pkcs7_free( &pkcs7 );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C:MBEDTLS_PKCS1_V15:MBEDTLS_RSA_C */
+void pkcs7_verify( char *pkcs7_file, char *crt, char *filetobesigned, int do_hash_alg, int res_expect )
+{
+ unsigned char *pkcs7_buf = NULL;
+ size_t buflen;
+ unsigned char *data = NULL;
+ unsigned char hash[32];
+ struct stat st;
+ size_t datalen;
+ int res;
+ FILE *file;
+ const mbedtls_md_info_t *md_info;
+ mbedtls_md_type_t md_alg;
+
+ mbedtls_pkcs7 pkcs7;
+ mbedtls_x509_crt x509;
+
+ USE_PSA_INIT();
+
+ mbedtls_pkcs7_init( &pkcs7 );
+ mbedtls_x509_crt_init( &x509 );
+
+ res = mbedtls_x509_crt_parse_file( &x509, crt );
+ TEST_ASSERT( res == 0 );
+
+ res = mbedtls_pk_load_file( pkcs7_file, &pkcs7_buf, &buflen );
+ TEST_ASSERT( res == 0 );
+
+ res = mbedtls_pkcs7_parse_der( &pkcs7, pkcs7_buf, buflen );
+ TEST_ASSERT( res == MBEDTLS_PKCS7_SIGNED_DATA );
+
+ res = stat( filetobesigned, &st );
+ TEST_ASSERT( res == 0 );
+
+ file = fopen( filetobesigned, "rb" );
+ TEST_ASSERT( file != NULL );
+
+ datalen = st.st_size;
+ data = mbedtls_calloc( datalen, 1 );
+ TEST_ASSERT( data != NULL );
+
+ buflen = fread( (void *)data , sizeof( unsigned char ), datalen, file );
+ TEST_ASSERT( buflen == datalen );
+ fclose( file );
+
+ if( do_hash_alg )
+ {
+ res = mbedtls_oid_get_md_alg( &pkcs7.signed_data.digest_alg_identifiers, &md_alg );
+ TEST_ASSERT( res == 0 );
+ TEST_ASSERT( md_alg == (mbedtls_md_type_t) do_hash_alg );
+ md_info = mbedtls_md_info_from_type( md_alg );
+
+ res = mbedtls_md( md_info, data, datalen, hash );
+ TEST_ASSERT( res == 0 );
+
+ res = mbedtls_pkcs7_signed_hash_verify( &pkcs7, &x509, hash, sizeof(hash) );
+ }
+ else
+ {
+ res = mbedtls_pkcs7_signed_data_verify( &pkcs7, &x509, data, datalen );
+ }
+ TEST_ASSERT( res == res_expect );
+
+exit:
+ mbedtls_x509_crt_free( &x509 );
+ mbedtls_free( data );
+ mbedtls_pkcs7_free( &pkcs7 );
+ mbedtls_free( pkcs7_buf );
+ USE_PSA_DONE();
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C:MBEDTLS_PKCS1_V15:MBEDTLS_RSA_C */
+void pkcs7_verify_multiple_signers( char *pkcs7_file, char *crt1, char *crt2, char *filetobesigned, int do_hash_alg, int res_expect )
+{
+ unsigned char *pkcs7_buf = NULL;
+ size_t buflen;
+ unsigned char *data = NULL;
+ unsigned char hash[32];
+ struct stat st;
+ size_t datalen;
+ int res;
+ FILE *file;
+ const mbedtls_md_info_t *md_info;
+ mbedtls_md_type_t md_alg;
+
+ mbedtls_pkcs7 pkcs7;
+ mbedtls_x509_crt x509_1;
+ mbedtls_x509_crt x509_2;
+
+ USE_PSA_INIT();
+
+ mbedtls_pkcs7_init( &pkcs7 );
+ mbedtls_x509_crt_init( &x509_1 );
+ mbedtls_x509_crt_init( &x509_2 );
+
+ res = mbedtls_pk_load_file( pkcs7_file, &pkcs7_buf, &buflen );
+ TEST_ASSERT( res == 0 );
+
+ res = mbedtls_pkcs7_parse_der( &pkcs7, pkcs7_buf, buflen );
+ TEST_ASSERT( res == MBEDTLS_PKCS7_SIGNED_DATA );
+
+ TEST_ASSERT( pkcs7.signed_data.no_of_signers == 2 );
+
+ res = mbedtls_x509_crt_parse_file( &x509_1, crt1 );
+ TEST_ASSERT( res == 0 );
+
+ res = mbedtls_x509_crt_parse_file( &x509_2, crt2 );
+ TEST_ASSERT( res == 0 );
+
+ res = stat( filetobesigned, &st );
+ TEST_ASSERT( res == 0 );
+
+ file = fopen( filetobesigned, "rb" );
+ TEST_ASSERT( file != NULL );
+
+ datalen = st.st_size;
+ data = ( unsigned char* ) calloc( datalen, sizeof(unsigned char) );
+ buflen = fread( ( void * )data , sizeof( unsigned char ), datalen, file );
+ TEST_ASSERT( buflen == datalen );
+
+ fclose( file );
+
+ if( do_hash_alg )
+ {
+ res = mbedtls_oid_get_md_alg( &pkcs7.signed_data.digest_alg_identifiers, &md_alg );
+ TEST_ASSERT( res == 0 );
+ TEST_ASSERT( md_alg == MBEDTLS_MD_SHA256 );
+
+ md_info = mbedtls_md_info_from_type( md_alg );
+
+ res = mbedtls_md( md_info, data, datalen, hash );
+ TEST_ASSERT( res == 0 );
+
+ res = mbedtls_pkcs7_signed_hash_verify( &pkcs7, &x509_1, hash, sizeof(hash) );
+ TEST_ASSERT( res == res_expect );
+ }
+ else
+ {
+ res = mbedtls_pkcs7_signed_data_verify( &pkcs7, &x509_1, data, datalen );
+ TEST_ASSERT( res == res_expect );
+ }
+
+ res = mbedtls_pkcs7_signed_data_verify( &pkcs7, &x509_2, data, datalen );
+ TEST_ASSERT( res == res_expect );
+
+exit:
+ mbedtls_x509_crt_free( &x509_1 );
+ mbedtls_x509_crt_free( &x509_2 );
+ mbedtls_pkcs7_free( &pkcs7 );
+ mbedtls_free( data );
+ mbedtls_free( pkcs7_buf );
+ USE_PSA_DONE();
+}
+/* END_CASE */