pkcs7: add support for signed data

OpenSSL provides APIs to generate only the signted data
format PKCS7 i.e. without content type OID. This patch
adds support to parse the data correctly even if formatted
only as signed data

Signed-off-by: Nayna Jain <nayna@linux.ibm.com>
diff --git a/include/mbedtls/pkcs7.h b/include/mbedtls/pkcs7.h
index 3f87dc3..59da147 100644
--- a/include/mbedtls/pkcs7.h
+++ b/include/mbedtls/pkcs7.h
@@ -97,6 +97,20 @@
 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
@@ -168,7 +182,7 @@
  *                 \p buf. In particular, \p buf may be destroyed or reused
  *                 after this call returns.
  *
- * \return         \c 0, if successful.
+ * \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,
diff --git a/library/pkcs7.c b/library/pkcs7.c
index c3236e1..5563f33 100644
--- a/library/pkcs7.c
+++ b/library/pkcs7.c
@@ -103,6 +103,7 @@
 {
     size_t len = 0;
     int ret;
+    unsigned char *start = *p;
 
     ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
                                             | MBEDTLS_ASN1_SEQUENCE );
@@ -110,8 +111,10 @@
         return( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO + ret );
 
     ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_OID );
-    if( ret != 0 )
+    if( ret != 0 ) {
+        *p = start;
         return( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO + ret );
+    }
 
     pkcs7->tag = MBEDTLS_ASN1_OID;
     pkcs7->len = len;
@@ -428,6 +431,7 @@
     unsigned char *end;
     size_t len = 0;
     int ret;
+    int isoidset = 0;
 
     if( !pkcs7 )
         return( MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA );
@@ -444,7 +448,10 @@
 
     ret = pkcs7_get_content_info_type( &start, end, &pkcs7->content_type_oid );
     if( ret != 0 )
-        goto out;
+    {
+        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 )
@@ -463,17 +470,31 @@
         goto out;
     }
 
+    isoidset = 1;
     start = start + pkcs7->content_type_oid.len;
 
     ret = pkcs7_get_next_content_len( &start, end, &len );
     if( ret != 0 )
         goto out;
 
+try_data:
     ret = pkcs7_get_signed_data( start, 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 )
+    if ( ret < 0 )
         mbedtls_pkcs7_free( pkcs7 );
+
     return( ret );
 }
 
diff --git a/tests/data_files/Makefile b/tests/data_files/Makefile
index 288b01f..dbe3234 100644
--- a/tests/data_files/Makefile
+++ b/tests/data_files/Makefile
@@ -1223,6 +1223,11 @@
 	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/suites/test_suite_pkcs7.data b/tests/suites/test_suite_pkcs7.data
index 870e83b..75ee9f6 100644
--- a/tests/suites/test_suite_pkcs7.data
+++ b/tests/suites/test_suite_pkcs7.data
@@ -51,3 +51,6 @@
 
 PKCS7 Signed Data Parse Failure Corrupt signerInfo.serial #15.2
 pkcs7_parse_failure:"data_files/pkcs7_signerInfo_serial_invalid_size.der"
+
+PKCS7 Only Signed Data Parse Pass #15
+pkcs7_parse:"data_files/pkcs7_data_cert_signeddata_sha256.der"
diff --git a/tests/suites/test_suite_pkcs7.function b/tests/suites/test_suite_pkcs7.function
index b5ef2ef..d85a455 100644
--- a/tests/suites/test_suite_pkcs7.function
+++ b/tests/suites/test_suite_pkcs7.function
@@ -29,7 +29,7 @@
     TEST_ASSERT( res == 0 );
 
     res = mbedtls_pkcs7_parse_der( &pkcs7, pkcs7_buf, buflen );
-    TEST_ASSERT( res == 0 );
+    TEST_ASSERT( res == MBEDTLS_PKCS7_SIGNED_DATA );
 
 exit:
     mbedtls_free( pkcs7_buf );
@@ -52,7 +52,7 @@
     TEST_ASSERT( res == 0 );
 
     res = mbedtls_pkcs7_parse_der( &pkcs7, pkcs7_buf, buflen );
-    TEST_ASSERT( res == 0 );
+    TEST_ASSERT( res == MBEDTLS_PKCS7_SIGNED_DATA );
 
 exit:
     mbedtls_free( pkcs7_buf );
@@ -210,10 +210,10 @@
     TEST_ASSERT( res == 0 );
 
     res = mbedtls_pkcs7_parse_der( &pkcs7, pkcs7_buf, buflen );
-    TEST_ASSERT( res == 0 );
+    TEST_ASSERT( res == MBEDTLS_PKCS7_SIGNED_DATA );
     mbedtls_free( pkcs7_buf );
 
-    res = stat(filetobesigned, &st);
+    res = stat( filetobesigned, &st );
     TEST_ASSERT( res == 0 );
 
     file = fopen( filetobesigned, "rb" );
@@ -263,9 +263,9 @@
     TEST_ASSERT( res == 0 );
 
     res = mbedtls_pkcs7_parse_der( &pkcs7, pkcs7_buf, buflen );
-    TEST_ASSERT( res == 0 );
+    TEST_ASSERT( res == MBEDTLS_PKCS7_SIGNED_DATA );
 
-    res = stat(filetobesigned, &st);
+    res = stat( filetobesigned, &st );
     TEST_ASSERT( res == 0 );
 
     file = fopen( filetobesigned, "rb" );
@@ -319,12 +319,12 @@
     TEST_ASSERT( res == 0 );
 
     res = mbedtls_pkcs7_parse_der( &pkcs7, pkcs7_buf, buflen );
-    TEST_ASSERT( res == 0 );
+    TEST_ASSERT( res == MBEDTLS_PKCS7_SIGNED_DATA );
 
     res = mbedtls_x509_crt_parse_file( &x509, crt );
     TEST_ASSERT( res == 0 );
 
-    res = stat(filetobesigned, &st);
+    res = stat( filetobesigned, &st );
     TEST_ASSERT( res == 0 );
 
     file = fopen( filetobesigned, "rb" );
@@ -369,12 +369,12 @@
     TEST_ASSERT( res == 0 );
 
     res = mbedtls_pkcs7_parse_der( &pkcs7, pkcs7_buf, buflen );
-    TEST_ASSERT( res == 0 );
+    TEST_ASSERT( res == MBEDTLS_PKCS7_SIGNED_DATA );
 
     res = mbedtls_x509_crt_parse_file( &x509, crt );
     TEST_ASSERT( res == 0 );
 
-    res = stat(filetobesigned, &st);
+    res = stat( filetobesigned, &st );
     TEST_ASSERT( res == 0 );
 
     file = fopen( filetobesigned, "rb" );