diff mbox series

[v3,12/15] crypto: add out-of-tree mbedtls pkcs7 parser

Message ID 20200401003426.7198-13-erichte@linux.ibm.com
State Superseded
Headers show
Series Add initial secure variable storage and backend drivers | expand

Checks

Context Check Description
snowpatch_ozlabs/apply_patch fail Failed to apply to any branch
snowpatch_ozlabs/apply_patch warning Failed to apply on branch master (6826095796c91583f344950ff76ef8ccf6e756b5)

Commit Message

Eric Richter April 1, 2020, 12:34 a.m. UTC
From: Nayna Jain <nayna@linux.ibm.com>

This patch adds a pkcs7 parser for mbedtls that hasn't yet
gone upstream. Once/if that implementation is accepted,
this patch can be removed.

Signed-off-by: Nayna Jain <nayna@linux.ibm.com>
Signed-off-by: Eric Richter <erichte@linux.ibm.com>
---
 libstb/crypto/Makefile.inc       |   4 +-
 libstb/crypto/mbedtls-config.h   |   1 +
 libstb/crypto/pkcs7/Makefile.inc |  12 +
 libstb/crypto/pkcs7/pkcs7.c      | 508 +++++++++++++++++++++++++++++++
 libstb/crypto/pkcs7/pkcs7.h      | 151 +++++++++
 5 files changed, 675 insertions(+), 1 deletion(-)
 create mode 100644 libstb/crypto/pkcs7/Makefile.inc
 create mode 100644 libstb/crypto/pkcs7/pkcs7.c
 create mode 100644 libstb/crypto/pkcs7/pkcs7.h

Comments

Stefan Berger April 17, 2020, 6:14 p.m. UTC | #1
On 3/31/20 8:34 PM, Eric Richter wrote:
> From: Nayna Jain <nayna@linux.ibm.com>
>
> This patch adds a pkcs7 parser for mbedtls that hasn't yet
> gone upstream. Once/if that implementation is accepted,
> this patch can be removed.


It looks like it implements a subset of pkcs7, basically only the parts 
you need, right?


>
> Signed-off-by: Nayna Jain <nayna@linux.ibm.com>
> Signed-off-by: Eric Richter <erichte@linux.ibm.com>
> ---
>   libstb/crypto/Makefile.inc       |   4 +-
>   libstb/crypto/mbedtls-config.h   |   1 +
>   libstb/crypto/pkcs7/Makefile.inc |  12 +
>   libstb/crypto/pkcs7/pkcs7.c      | 508 +++++++++++++++++++++++++++++++
>   libstb/crypto/pkcs7/pkcs7.h      | 151 +++++++++
>   5 files changed, 675 insertions(+), 1 deletion(-)
>   create mode 100644 libstb/crypto/pkcs7/Makefile.inc
>   create mode 100644 libstb/crypto/pkcs7/pkcs7.c
>   create mode 100644 libstb/crypto/pkcs7/pkcs7.h
>
> diff --git a/libstb/crypto/Makefile.inc b/libstb/crypto/Makefile.inc
> index 42b5d8b9..ed2387e3 100644
> --- a/libstb/crypto/Makefile.inc
> +++ b/libstb/crypto/Makefile.inc
> @@ -42,6 +42,8 @@ MBEDTLS_SRCS = $(addprefix mbedtls/library/,$(MBED_CRYPTO_SRCS) $(MBED_X509_SRCS
>   
>   MBEDTLS_OBJS = $(MBEDTLS_SRCS:%.c=%.o)
>   
> +include $(CRYPTO_DIR)/pkcs7/Makefile.inc
> +
>   CRYPTO = $(CRYPTO_DIR)/built-in.a
>   
> -$(CRYPTO): $(MBEDTLS_OBJS:%=$(CRYPTO_DIR)/%)
> +$(CRYPTO): $(MBEDTLS_OBJS:%=$(CRYPTO_DIR)/%) $(PKCS7)
> diff --git a/libstb/crypto/mbedtls-config.h b/libstb/crypto/mbedtls-config.h
> index 414bbfd8..b1952aef 100644
> --- a/libstb/crypto/mbedtls-config.h
> +++ b/libstb/crypto/mbedtls-config.h
> @@ -72,6 +72,7 @@
>   //#define MBEDTLS_PEM_PARSE_C
>   #define MBEDTLS_PK_C
>   #define MBEDTLS_PK_PARSE_C
> +#define MBEDTLS_PKCS7_USE_C
>   //#define MBEDTLS_PK_WRITE_C
>   #define MBEDTLS_PLATFORM_C
>   #define MBEDTLS_RSA_C
> diff --git a/libstb/crypto/pkcs7/Makefile.inc b/libstb/crypto/pkcs7/Makefile.inc
> new file mode 100644
> index 00000000..bef339b5
> --- /dev/null
> +++ b/libstb/crypto/pkcs7/Makefile.inc
> @@ -0,0 +1,12 @@
> +
> +PKCS7_DIR = libstb/crypto/pkcs7
> +
> +SUBDIRS += $(PKCS7_DIR)
> +
> +PKCS7_SRCS = pkcs7.c
> +PKCS7_OBJS = $(PKCS7_SRCS:%.c=%.o)
> +PKCS7 = $(PKCS7_DIR)/built-in.a
> +
> +CFLAGS_$(PKCS7_DIR)/ = -I$(SRC)/$(LIBSTB_DIR)/crypto -DMBEDTLS_CONFIG_FILE='<mbedtls-config.h>'
> +
> +$(PKCS7): $(PKCS7_OBJS:%=$(PKCS7_DIR)/%)
> diff --git a/libstb/crypto/pkcs7/pkcs7.c b/libstb/crypto/pkcs7/pkcs7.c
> new file mode 100644
> index 00000000..f8097720
> --- /dev/null
> +++ b/libstb/crypto/pkcs7/pkcs7.c
> @@ -0,0 +1,508 @@
> +/* Copyright 2019 IBM Corp.
> + *
> + * 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.
> + */
> +
> +#if !defined(MBEDTLS_CONFIG_FILE)
> +#include "mbedtls/config.h"
> +#else
> +#include MBEDTLS_CONFIG_FILE
> +#endif
> +#if defined(MBEDTLS_PKCS7_USE_C)
> +
> +#include "mbedtls/x509.h"
> +#include "mbedtls/asn1.h"
> +#include "pkcs7.h"
> +#include "mbedtls/x509_crt.h"
> +#include "mbedtls/x509_crl.h"
> +#include "mbedtls/oid.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 <unistd.h>
> +
> +#if defined(MBEDTLS_PLATFORM_C)
> +#include "mbedtls/platform.h"
> +#include "mbedtls/platform_util.h"
> +#else
> +#include <stdio.h>
> +#include <stdlib.h>
> +#define mbedtls_free      free
> +#define mbedtls_calloc    calloc
> +#define mbedtls_printf    printf
> +#define mbedtls_snprintf  snprintf
> +#endif
> +
> +#if defined(MBEDTLS_HAVE_TIME)
> +#include "mbedtls/platform_time.h"
> +#endif
> +#if defined(MBEDTLS_HAVE_TIME_DATE)
> +#include <time.h>
> +#endif
> +
> +#if defined(MBEDTLS_FS_IO)
> +/*
> + * Load all data from a file into a given buffer.
> + *
> + * The file is expected to contain DER encoded data.
> + * A terminating null byte is always appended.
> + */
> +
> +int mbedtls_pkcs7_load_file( const char *path, unsigned char **buf, size_t *n )
> +{
> +    FILE *file;
> +    struct stat st;
> +    int rc;
> +
> +    rc = stat( path, &st );
> +    if ( rc )
> +	return ( MBEDTLS_ERR_PKCS7_FILE_IO_ERROR );


A style issue here for mbedtls. It looks like mbedtls does not want a 
space between 'return' and '('. Applies to everywhere...


> +
> +    if( ( file = fopen( path, "rb" ) ) == NULL )
> +        return ( MBEDTLS_ERR_PKCS7_FILE_IO_ERROR );
> +
> +    mbedtls_printf( "file size is %lu\n", st.st_size );
> +
> +    *n = (size_t) st.st_size;
> +
> +    *buf = mbedtls_calloc( 1, *n + 1 );
> +    if ( *buf == NULL )
> +        return( MBEDTLS_ERR_PKCS7_ALLOC_FAILED );
> +
> +    if( fread( *buf, 1, *n, file ) != *n )
> +    {
> +        fclose( file );
> +
> +        mbedtls_platform_zeroize( *buf, *n + 1 );
> +        mbedtls_free( *buf );
> +
> +        return( MBEDTLS_ERR_PKCS7_FILE_IO_ERROR );
> +    }
> +
> +    fclose( file );
> +
> +    (*buf)[*n] = '\0';
> +
> +    return( 0 );
> +}
> +#endif
> +
> +/**
> + * Initializes the pkcs7 structure.
> + */
> +void mbedtls_pkcs7_init( mbedtls_pkcs7 *pkcs7 )
> +{
> +    memset( pkcs7, 0, sizeof( mbedtls_pkcs7 ) );
> +}
> +
> +
> +static int pkcs7_get_next_content_len( unsigned char **p, unsigned char *end, size_t *len )
> +{
> +   int ret;
> +
> +   if ( ( ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_CONSTRUCTED
> +                          | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 )
> +      return ( MBEDTLS_ERR_PKCS7_INVALID_FORMAT + ret );
> +
> +   return ( 0 );
> +}
> +
> +/**
> + * version Version
> + * Version ::= INTEGER
> + **/
> +static int pkcs7_get_version( unsigned char **p, unsigned char *end, int *ver )
> +{
> +   int ret;
> +
> +   if ( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 )
> +       return ( MBEDTLS_ERR_PKCS7_INVALID_VERSION + ret );
> +
> +   return ( 0 );
> +}
> +
> +/**
> + * 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;


You changed the indentation. From what I can see mbedtls uses 4 spaces.


> +
> +      ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
> +                                            | MBEDTLS_ASN1_SEQUENCE );
> +      if ( ret )
> +              return ( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO + ret );
> +
> +      ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_OID );
> +      if ( ret )
> +              return ( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO + ret );
> +
> +      pkcs7->tag = MBEDTLS_ASN1_OID;
> +      pkcs7->len = len;
> +      pkcs7->p = *p;
> +
> +      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;
> +
> +      if ( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 )
> +          return ( MBEDTLS_ERR_PKCS7_INVALID_ALG + ret );
> +
> +      return ( 0 );
> +}
> +
> +/**
> + * 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;
> +
> +      ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
> +                                            | MBEDTLS_ASN1_SET );
> +      if ( ret != 0 )
> +              return ( MBEDTLS_ERR_PKCS7_INVALID_ALG + ret );
> +
> +      end = *p + len;
> +
> +      /** For now, it assumes there is only one digest algorithm specified **/
> +      ret = mbedtls_asn1_get_alg_null( p, end, alg );
> +      if ( ret )
> +              return ( MBEDTLS_ERR_PKCS7_INVALID_ALG + ret );
> +
> +      return ( 0 );
> +}
> +
> +/**
> + * certificates :: SET OF ExtendedCertificateOrCertificate,
> + * ExtendedCertificateOrCertificate ::= CHOICE {
> + *      certificate Certificate -- x509,
> + *      extendedCertificate[0] IMPLICIT ExtendedCertificate }
> + **/
> +static int pkcs7_get_certificates( unsigned char **buf, size_t buflen,
> +              mbedtls_x509_crt *certs )
> +{
> +      int ret;
> +
> +      if ( ( ret = mbedtls_x509_crt_parse( certs, *buf, buflen ) ) < 0 )
> +          return ( ret );
> +
> +      /**
> +       * Currently we do not check for certificate chain, so we are not handling "> 0" case.
> +       * Might have to revisit soon.
> +       **/
> +
> +      return ( 0 );
> +}
> +
> +/**
> + * EncryptedDigest ::= OCTET STRING
> + **/
> +static int pkcs7_get_signature( unsigned char **p, unsigned char *end,
> +              mbedtls_pkcs7_buf *signature )
> +{
> +      int ret;
> +      size_t len = 0;
> +
> +      ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
> +      if ( ret != 0 )
> +              return ( MBEDTLS_ERR_PKCS7_INVALID_SIGNATURE + ret );
> +
> +      signature->tag = MBEDTLS_ASN1_OCTET_STRING;
> +      signature->len = len;
> +      signature->p = *p;
> +
> +      return ( 0 );
> +}
> +
> +/**
> + * SignerInfo ::= SEQUENCE {
> + *      version Version;
> + *      issuerAndSerialNumber   IssuerAndSerialNumber,
> + *      digestAlgorithm DigestAlgorithmIdentifier,
> + *      authenticatedAttributes
> + *              [0] IMPLICIT Attributes OPTIONAL,
> + *      digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
> + *      encryptedDigest EncryptedDigest,
> + *      unauthenticatedAttributes
> + *              [1] IMPLICIT Attributes OPTIONAL,

You are not parsing all of this, are you?


> + **/
> +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;
> +      size_t len = 0;
> +
> +      ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
> +                                            | MBEDTLS_ASN1_SET );
> +      if ( ret != 0 )
> +              return ( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO + ret );
> +
> +      end_set = *p + len;
> +
> +      ret = mbedtls_asn1_get_tag( p, end_set, &len, MBEDTLS_ASN1_CONSTRUCTED
> +                                                | MBEDTLS_ASN1_SEQUENCE );
> +      if ( ret != 0 )
> +              return ( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO + ret );
> +
> +      ret = mbedtls_asn1_get_int( p, end_set, &signers_set->version );
> +      if ( ret != 0 )
> +              return ( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO + ret );
> +
> +      ret = mbedtls_asn1_get_tag( p, end_set, &len, MBEDTLS_ASN1_CONSTRUCTED
> +                                                | MBEDTLS_ASN1_SEQUENCE );
> +      if ( ret != 0 )
> +              return ( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO + ret );
> +
> +      signers_set->issuer_raw.p = *p;
> +
> +      ret = mbedtls_asn1_get_tag( p, end_set, &len, MBEDTLS_ASN1_CONSTRUCTED
> +                                                | MBEDTLS_ASN1_SEQUENCE );
> +      if ( ret != 0 )
> +              return ( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO + ret );
> +
> +      ret  = mbedtls_x509_get_name( p, *p + len, &signers_set->issuer );
> +      if ( ret != 0 )
> +              return ( ret );
> +
> +      signers_set->issuer_raw.len =  *p - signers_set->issuer_raw.p;
> +
> +      ret = mbedtls_x509_get_serial( p, end_set, &signers_set->serial );
> +      if ( ret != 0 )
> +              return ( ret );
> +
> +      ret = pkcs7_get_digest_algorithm( p, end_set,
> +                                      &signers_set->alg_identifier );
> +      if ( ret != 0 )
> +              return ( ret );
> +
> +      ret = pkcs7_get_digest_algorithm( p, end_set,
> +                                      &signers_set->sig_alg_identifier );
> +      if ( ret != 0 )
> +              return ( ret );
> +
> +      ret = pkcs7_get_signature( p, end, &signers_set->sig );
> +      if ( ret != 0 )
> +              return ( ret );
> +
> +      signers_set->next = NULL;
> +
> +      return ( 0 );
> +}
> +
> +/**
> + * 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;
> +      size_t len = 0;
> +      int ret;
> +
> +      ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
> +                                             | MBEDTLS_ASN1_SEQUENCE );
> +      if ( ret != 0 )
> +              return ( MBEDTLS_ERR_PKCS7_INVALID_FORMAT + ret );
> +
> +      /* Get version of signed data */
> +      ret = pkcs7_get_version( &p, end, &signed_data->version );
> +      if ( ret != 0 )
> +              return ( ret );
> +
> +      /* If version != 1, return invalid version */
> +      if ( signed_data->version != MBEDTLS_PKCS7_SUPPORTED_VERSION ) {
> +              mbedtls_printf("Invalid version\n");
> +              return ( MBEDTLS_ERR_PKCS7_INVALID_VERSION );
> +      }
> +
> +      /* Get digest algorithm */
> +      ret = pkcs7_get_digest_algorithm_set( &p, end,
> +                                          &signed_data->digest_alg_identifiers );
> +      if ( ret != 0 ) {
> +              mbedtls_printf("error getting digest algorithms\n");
> +              return ( ret );
> +      }
> +
> +      if ( signed_data->digest_alg_identifiers.len != strlen( MBEDTLS_OID_DIGEST_ALG_SHA256 ) )
> +              return ( MBEDTLS_ERR_PKCS7_INVALID_ALG );
> +
> +      if ( memcmp( signed_data->digest_alg_identifiers.p, MBEDTLS_OID_DIGEST_ALG_SHA256,
> +                 signed_data->digest_alg_identifiers.len ) ) {
> +              mbedtls_fprintf(stdout, "Digest Algorithm other than SHA256 is not supported\n");
> +              return ( MBEDTLS_ERR_PKCS7_INVALID_ALG );
> +      }
> +
> +      /* Do not expect any content */
> +      ret = pkcs7_get_content_info_type( &p, end, &signed_data->content.oid );
> +      if ( ret != 0 )
> +              return ( ret );
> +
> +      if ( memcmp( signed_data->content.oid.p, MBEDTLS_OID_PKCS7_DATA,
> +                 signed_data->content.oid.len ) ) {
> +              mbedtls_printf("Invalid PKCS7 data\n");
> +              return ( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO ) ;
> +      }
> +
> +      p = p + signed_data->content.oid.len;
> +
> +      ret = pkcs7_get_next_content_len( &p, end, &len );
> +      if ( ret != 0 )
> +              return ( ret );
> +
> +      /* Get certificates */
> +      mbedtls_x509_crt_init( &signed_data->certs );
> +      ret = pkcs7_get_certificates( &p, len, &signed_data->certs );
> +      if ( ret != 0 )
> +              return ( ret ) ;
> +
> +      p = p + len;
> +
> +      /* Get signers info */
> +      ret = pkcs7_get_signers_info_set( &p, end, &signed_data->signers );
> +      if ( ret != 0 )
> +              return ( ret );
> +
> +      return ( ret );
> +}
> +
> +int mbedtls_pkcs7_parse_der( const unsigned char *buf, const int buflen,
> +                      mbedtls_pkcs7 *pkcs7 )
> +{
> +      unsigned char *start;
> +      unsigned char *end;
> +      size_t len = 0;
> +      int ret;
> +
> +      /* use internal buffer for parsing */
> +      start = ( unsigned char * )buf;


What mbedtls seems to be doing in similar(!) cases is mbedtls_calloc() a 
buffer and copy things over [mbedtls_x509_crl_parse_der]. So they have 
functions with signature 'const unsigned char*' but then don't seem to 
cast like you do here but use a 2nd buffer, but then they keep the plain 
buffer around. In your case it's the asn1 parser functions that don't 
seem to take a 'const' buffer, so you never know whether you can offer 
the 'const'.


> +      end = start + buflen;
> +
> +      if (!pkcs7)
> +              return ( MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA );
> +
> +      ret = pkcs7_get_content_info_type( &start, end, &pkcs7->content_type_oid );
> +      if ( ret != 0 )
> +              goto out;
> +
> +      if ( ( !memcmp( pkcs7->content_type_oid.p, MBEDTLS_OID_PKCS7_DATA,
> +                 pkcs7->content_type_oid.len ) )
> +          || ( !memcmp( pkcs7->content_type_oid.p, MBEDTLS_OID_PKCS7_ENCRYPTED_DATA,
> +                 pkcs7->content_type_oid.len ) )
> +          || ( !memcmp(pkcs7->content_type_oid.p, MBEDTLS_OID_PKCS7_ENVELOPED_DATA,
> +                 pkcs7->content_type_oid.len ) )
> +            || ( !memcmp(pkcs7->content_type_oid.p, MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA,
> +                 pkcs7->content_type_oid.len ) )
> +            || ( !memcmp(pkcs7->content_type_oid.p, MBEDTLS_OID_PKCS7_DIGESTED_DATA,
> +                 pkcs7->content_type_oid.len ) )
> +          || ( !memcmp(pkcs7->content_type_oid.p, MBEDTLS_OID_PKCS7_ENCRYPTED_DATA,
> +                 pkcs7->content_type_oid.len ) ) ) {
> +              mbedtls_printf("Unsupported PKCS7 data type\n");
> +              ret =  MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
> +              goto out;
> +      }
> +
> +      if ( ( memcmp( pkcs7->content_type_oid.p, MBEDTLS_OID_PKCS7_SIGNED_DATA,
> +                 pkcs7->content_type_oid.len ) ) ) {
> +               mbedtls_printf("Invalid PKCS7 data type\n");
> +               ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
> +               goto out;
> +      }
> +      mbedtls_printf("Content type is SignedData\n");
> +
> +      start = start + pkcs7->content_type_oid.len;
> +
> +      ret = pkcs7_get_next_content_len( &start, end, &len );
> +      if ( ret != 0 )
> +              goto out;
> +
> +      ret = pkcs7_get_signed_data( start, len, &pkcs7->signed_data );
> +      if ( ret != 0 )
> +              goto out;
> +
> +out:
> +      return ( ret );
> +}
> +
> +int mbedtls_pkcs7_signed_data_verify( mbedtls_pkcs7 *pkcs7, mbedtls_x509_crt *cert, const unsigned char *data, int datalen )
> +{
> +
> +       int ret;
> +       unsigned char hash[32];
> +       mbedtls_pk_context pk_cxt = cert->pk;
> +       const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 );
> +
> +       mbedtls_md( md_info, data, datalen, hash );
> +       ret = mbedtls_pk_verify( &pk_cxt, MBEDTLS_MD_SHA256, hash, sizeof(hash), pkcs7->signed_data.signers.sig.p, pkcs7->signed_data.signers.sig.len );
> +
> +       mbedtls_printf("Verification return code is %04x\n", ret);
> +
> +       return ( ret );
> +}
> +
> +/*
> + * Unallocate all pkcs7 data
> + */
> +void mbedtls_pkcs7_free(  mbedtls_pkcs7 *pkcs7 )
> +{
> +	mbedtls_x509_name *name_cur;
> +	mbedtls_x509_name *name_prv;
> +
> +	if (pkcs7 == NULL)
> +		return;
> +
> +	mbedtls_x509_crt_free( &pkcs7->signed_data.certs );
> +	mbedtls_x509_crl_free( &pkcs7->signed_data.crl );
> +
> +	name_cur = pkcs7->signed_data.signers.issuer.next;
> +        while( name_cur != NULL )
> +        {
> +            name_prv = name_cur;
> +            name_cur = name_cur->next;
> +            mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
> +            mbedtls_free( name_prv );
> +        }
> +}
> +
> +#endif
> diff --git a/libstb/crypto/pkcs7/pkcs7.h b/libstb/crypto/pkcs7/pkcs7.h
> new file mode 100644
> index 00000000..7f14b4b8
> --- /dev/null
> +++ b/libstb/crypto/pkcs7/pkcs7.h
> @@ -0,0 +1,151 @@
> +/**
> + * \file pkcs7.h
> + *
> + * \brief PKCS7 generic defines and structures
> + */
> +/*
> + *  Copyright (C) 2019,  IBM Corp, All Rights Reserved
> + *  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.
> + *
> + *  This file is part of mbed TLS (https://tls.mbed.org)
> + */
> +#ifndef MBEDTLS_PKCS7_H
> +#define MBEDTLS_PKCS7_H
> +
> +#if !defined(MBEDTLS_CONFIG_FILE)
> +#include "config.h"
> +#else
> +#include MBEDTLS_CONFIG_FILE
> +#endif
> +
> +#include "mbedtls/asn1.h"
> +#include "mbedtls/x509.h"
> +#include "mbedtls/x509_crt.h"
> +
> +/**
> + * \name PKCS7 Error codes
> + * \{
> + */
> +#define MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE              -0x7080  /**< Unavailable feature, e.g. anything other than signed data. */
> +#define MBEDTLS_ERR_PKCS7_INVALID_FORMAT                   -0x7100  /**< The CRT/CRL format is invalid, e.g. different type expected. */
> +#define MBEDTLS_ERR_PKCS7_INVALID_VERSION                  -0x7180  /**< The PKCS7 version element is invalid or cannot be parsed. */
> +#define MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO             -0x7200  /**< The PKCS7 content info invalid or cannot be parsed. */
> +#define MBEDTLS_ERR_PKCS7_INVALID_ALG                      -0x7280  /**< The algorithm tag or value is invalid or cannot be parsed. */
> +#define MBEDTLS_ERR_PKCS7_INVALID_SIGNATURE                -0x7300  /**< Error parsing the signature */
> +#define MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO              -0x7380  /**< Error parsing the signer's info */
> +#define MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA                   -0x7400  /**< Input invalid. */
> +#define MBEDTLS_ERR_PKCS7_ALLOC_FAILED                     -0x7480  /**< Allocation of memory failed. */
> +#define MBEDTLS_ERR_PKCS7_FILE_IO_ERROR                    -0x7500  /**< File Read/Write Error */
> +/* \} 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;
> +
> +/**
> + * Structure holding PKCS7 signer info
> + */
> +typedef struct mbedtls_pkcs7_signer_info {
> +        int version;
> +        mbedtls_x509_buf serial;
> +        mbedtls_x509_name issuer;
> +        mbedtls_x509_buf issuer_raw;
> +        mbedtls_x509_buf alg_identifier;
> +        mbedtls_x509_buf sig_alg_identifier;
> +        mbedtls_x509_buf sig;
> +        struct mbedtls_pkcs7_signer_info *next;
> +}
> +mbedtls_pkcs7_signer_info;
> +
> +/**
> + * Structure holding attached data as part of PKCS7 signed data format
> + */
> +typedef struct mbedtls_pkcs7_data {
> +        mbedtls_pkcs7_buf oid;
> +        mbedtls_pkcs7_buf data;
> +}
> +mbedtls_pkcs7_data;
> +
> +/**
> + * Structure holding the signed data section
> + */
> +typedef struct mbedtls_pkcs7_signed_data {
> +        int version;
> +        mbedtls_pkcs7_buf digest_alg_identifiers;
> +        struct mbedtls_pkcs7_data content;
> +        mbedtls_x509_crt certs;
> +        mbedtls_x509_crl crl;
> +        struct mbedtls_pkcs7_signer_info signers;
> +}
> +mbedtls_pkcs7_signed_data;
> +
> +/**
> + * Structure holding PKCS7 structure, only signed data for now
> + */
> +typedef struct mbedtls_pkcs7 {
> +        mbedtls_pkcs7_buf content_type_oid;
> +        struct mbedtls_pkcs7_signed_data signed_data;
> +}
> +mbedtls_pkcs7;
> +
> +void mbedtls_pkcs7_init( mbedtls_pkcs7 *pkcs7 );
> +
> +int mbedtls_pkcs7_parse_der(const unsigned char *buf, const int buflen, mbedtls_pkcs7 *pkcs7);
> +
> +int mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 *pkcs7, mbedtls_x509_crt *cert, const unsigned char *data, int datalen);
> +
> +int mbedtls_pkcs7_load_file( const char *path, unsigned char **buf, size_t *n );
> +
> +void mbedtls_pkcs7_free(  mbedtls_pkcs7 *pkcs7 );
> +
> +/*
> + * PKCS#7 OIDs
> + */
> +#define MBEDTLS_OID_PKCS7				MBEDTLS_OID_PKCS "\x07" /**< pkcs-7 */
> +#define MBEDTLS_OID_PKCS7_DATA				MBEDTLS_OID_PKCS7 "\x01" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */
> +#define MBEDTLS_OID_PKCS7_SIGNED_DATA			MBEDTLS_OID_PKCS7 "\x02" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */
> +#define MBEDTLS_OID_PKCS7_ENVELOPED_DATA		MBEDTLS_OID_PKCS7 "\x03" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */
> +#define MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA	MBEDTLS_OID_PKCS7 "\x04" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */
> +#define MBEDTLS_OID_PKCS7_DIGESTED_DATA			MBEDTLS_OID_PKCS7 "\x05" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */
> +#define MBEDTLS_OID_PKCS7_ENCRYPTED_DATA		MBEDTLS_OID_PKCS7 "\x06" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* pkcs7.h */
diff mbox series

Patch

diff --git a/libstb/crypto/Makefile.inc b/libstb/crypto/Makefile.inc
index 42b5d8b9..ed2387e3 100644
--- a/libstb/crypto/Makefile.inc
+++ b/libstb/crypto/Makefile.inc
@@ -42,6 +42,8 @@  MBEDTLS_SRCS = $(addprefix mbedtls/library/,$(MBED_CRYPTO_SRCS) $(MBED_X509_SRCS
 
 MBEDTLS_OBJS = $(MBEDTLS_SRCS:%.c=%.o)
 
+include $(CRYPTO_DIR)/pkcs7/Makefile.inc
+
 CRYPTO = $(CRYPTO_DIR)/built-in.a
 
-$(CRYPTO): $(MBEDTLS_OBJS:%=$(CRYPTO_DIR)/%)
+$(CRYPTO): $(MBEDTLS_OBJS:%=$(CRYPTO_DIR)/%) $(PKCS7)
diff --git a/libstb/crypto/mbedtls-config.h b/libstb/crypto/mbedtls-config.h
index 414bbfd8..b1952aef 100644
--- a/libstb/crypto/mbedtls-config.h
+++ b/libstb/crypto/mbedtls-config.h
@@ -72,6 +72,7 @@ 
 //#define MBEDTLS_PEM_PARSE_C
 #define MBEDTLS_PK_C
 #define MBEDTLS_PK_PARSE_C
+#define MBEDTLS_PKCS7_USE_C
 //#define MBEDTLS_PK_WRITE_C
 #define MBEDTLS_PLATFORM_C
 #define MBEDTLS_RSA_C
diff --git a/libstb/crypto/pkcs7/Makefile.inc b/libstb/crypto/pkcs7/Makefile.inc
new file mode 100644
index 00000000..bef339b5
--- /dev/null
+++ b/libstb/crypto/pkcs7/Makefile.inc
@@ -0,0 +1,12 @@ 
+
+PKCS7_DIR = libstb/crypto/pkcs7
+
+SUBDIRS += $(PKCS7_DIR)
+
+PKCS7_SRCS = pkcs7.c
+PKCS7_OBJS = $(PKCS7_SRCS:%.c=%.o)
+PKCS7 = $(PKCS7_DIR)/built-in.a
+
+CFLAGS_$(PKCS7_DIR)/ = -I$(SRC)/$(LIBSTB_DIR)/crypto -DMBEDTLS_CONFIG_FILE='<mbedtls-config.h>'
+
+$(PKCS7): $(PKCS7_OBJS:%=$(PKCS7_DIR)/%)
diff --git a/libstb/crypto/pkcs7/pkcs7.c b/libstb/crypto/pkcs7/pkcs7.c
new file mode 100644
index 00000000..f8097720
--- /dev/null
+++ b/libstb/crypto/pkcs7/pkcs7.c
@@ -0,0 +1,508 @@ 
+/* Copyright 2019 IBM Corp.
+ *
+ * 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.
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+#if defined(MBEDTLS_PKCS7_USE_C)
+
+#include "mbedtls/x509.h"
+#include "mbedtls/asn1.h"
+#include "pkcs7.h"
+#include "mbedtls/x509_crt.h"
+#include "mbedtls/x509_crl.h"
+#include "mbedtls/oid.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 <unistd.h>
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#include "mbedtls/platform_util.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#define mbedtls_free      free
+#define mbedtls_calloc    calloc
+#define mbedtls_printf    printf
+#define mbedtls_snprintf  snprintf
+#endif
+
+#if defined(MBEDTLS_HAVE_TIME)
+#include "mbedtls/platform_time.h"
+#endif
+#if defined(MBEDTLS_HAVE_TIME_DATE)
+#include <time.h>
+#endif
+
+#if defined(MBEDTLS_FS_IO)
+/*
+ * Load all data from a file into a given buffer.
+ *
+ * The file is expected to contain DER encoded data.
+ * A terminating null byte is always appended.
+ */
+
+int mbedtls_pkcs7_load_file( const char *path, unsigned char **buf, size_t *n )
+{
+    FILE *file;
+    struct stat st;
+    int rc;
+
+    rc = stat( path, &st );
+    if ( rc )
+	return ( MBEDTLS_ERR_PKCS7_FILE_IO_ERROR );
+
+    if( ( file = fopen( path, "rb" ) ) == NULL )
+        return ( MBEDTLS_ERR_PKCS7_FILE_IO_ERROR );
+
+    mbedtls_printf( "file size is %lu\n", st.st_size );
+
+    *n = (size_t) st.st_size;
+
+    *buf = mbedtls_calloc( 1, *n + 1 );
+    if ( *buf == NULL )
+        return( MBEDTLS_ERR_PKCS7_ALLOC_FAILED );
+
+    if( fread( *buf, 1, *n, file ) != *n )
+    {
+        fclose( file );
+
+        mbedtls_platform_zeroize( *buf, *n + 1 );
+        mbedtls_free( *buf );
+
+        return( MBEDTLS_ERR_PKCS7_FILE_IO_ERROR );
+    }
+
+    fclose( file );
+
+    (*buf)[*n] = '\0';
+
+    return( 0 );
+}
+#endif
+
+/**
+ * Initializes the pkcs7 structure.
+ */
+void mbedtls_pkcs7_init( mbedtls_pkcs7 *pkcs7 )
+{
+    memset( pkcs7, 0, sizeof( mbedtls_pkcs7 ) );
+}
+
+
+static int pkcs7_get_next_content_len( unsigned char **p, unsigned char *end, size_t *len )
+{
+   int ret;
+
+   if ( ( ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_CONSTRUCTED
+                          | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 )
+      return ( MBEDTLS_ERR_PKCS7_INVALID_FORMAT + ret );
+
+   return ( 0 );
+}
+
+/**
+ * version Version
+ * Version ::= INTEGER
+ **/
+static int pkcs7_get_version( unsigned char **p, unsigned char *end, int *ver )
+{
+   int ret;
+
+   if ( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 )
+       return ( MBEDTLS_ERR_PKCS7_INVALID_VERSION + ret );
+
+   return ( 0 );
+}
+
+/**
+ * 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;
+
+      ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
+                                            | MBEDTLS_ASN1_SEQUENCE );
+      if ( ret )
+              return ( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO + ret );
+
+      ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_OID );
+      if ( ret )
+              return ( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO + ret );
+
+      pkcs7->tag = MBEDTLS_ASN1_OID;
+      pkcs7->len = len;
+      pkcs7->p = *p;
+
+      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;
+
+      if ( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 )
+          return ( MBEDTLS_ERR_PKCS7_INVALID_ALG + ret );
+
+      return ( 0 );
+}
+
+/**
+ * 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;
+
+      ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
+                                            | MBEDTLS_ASN1_SET );
+      if ( ret != 0 )
+              return ( MBEDTLS_ERR_PKCS7_INVALID_ALG + ret );
+
+      end = *p + len;
+
+      /** For now, it assumes there is only one digest algorithm specified **/
+      ret = mbedtls_asn1_get_alg_null( p, end, alg );
+      if ( ret )
+              return ( MBEDTLS_ERR_PKCS7_INVALID_ALG + ret );
+
+      return ( 0 );
+}
+
+/**
+ * certificates :: SET OF ExtendedCertificateOrCertificate,
+ * ExtendedCertificateOrCertificate ::= CHOICE {
+ *      certificate Certificate -- x509,
+ *      extendedCertificate[0] IMPLICIT ExtendedCertificate }
+ **/
+static int pkcs7_get_certificates( unsigned char **buf, size_t buflen,
+              mbedtls_x509_crt *certs )
+{
+      int ret;
+
+      if ( ( ret = mbedtls_x509_crt_parse( certs, *buf, buflen ) ) < 0 )
+          return ( ret );
+
+      /**
+       * Currently we do not check for certificate chain, so we are not handling "> 0" case.
+       * Might have to revisit soon.
+       **/
+
+      return ( 0 );
+}
+
+/**
+ * EncryptedDigest ::= OCTET STRING
+ **/
+static int pkcs7_get_signature( unsigned char **p, unsigned char *end,
+              mbedtls_pkcs7_buf *signature )
+{
+      int ret;
+      size_t len = 0;
+
+      ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
+      if ( ret != 0 )
+              return ( MBEDTLS_ERR_PKCS7_INVALID_SIGNATURE + ret );
+
+      signature->tag = MBEDTLS_ASN1_OCTET_STRING;
+      signature->len = len;
+      signature->p = *p;
+
+      return ( 0 );
+}
+
+/**
+ * SignerInfo ::= SEQUENCE {
+ *      version Version;
+ *      issuerAndSerialNumber   IssuerAndSerialNumber,
+ *      digestAlgorithm DigestAlgorithmIdentifier,
+ *      authenticatedAttributes
+ *              [0] IMPLICIT Attributes OPTIONAL,
+ *      digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
+ *      encryptedDigest EncryptedDigest,
+ *      unauthenticatedAttributes
+ *              [1] IMPLICIT Attributes OPTIONAL,
+ **/
+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;
+      size_t len = 0;
+
+      ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
+                                            | MBEDTLS_ASN1_SET );
+      if ( ret != 0 )
+              return ( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO + ret );
+
+      end_set = *p + len;
+
+      ret = mbedtls_asn1_get_tag( p, end_set, &len, MBEDTLS_ASN1_CONSTRUCTED
+                                                | MBEDTLS_ASN1_SEQUENCE );
+      if ( ret != 0 )
+              return ( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO + ret );
+
+      ret = mbedtls_asn1_get_int( p, end_set, &signers_set->version );
+      if ( ret != 0 )
+              return ( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO + ret );
+
+      ret = mbedtls_asn1_get_tag( p, end_set, &len, MBEDTLS_ASN1_CONSTRUCTED
+                                                | MBEDTLS_ASN1_SEQUENCE );
+      if ( ret != 0 )
+              return ( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO + ret );
+
+      signers_set->issuer_raw.p = *p;
+
+      ret = mbedtls_asn1_get_tag( p, end_set, &len, MBEDTLS_ASN1_CONSTRUCTED
+                                                | MBEDTLS_ASN1_SEQUENCE );
+      if ( ret != 0 )
+              return ( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO + ret );
+
+      ret  = mbedtls_x509_get_name( p, *p + len, &signers_set->issuer );
+      if ( ret != 0 )
+              return ( ret );
+
+      signers_set->issuer_raw.len =  *p - signers_set->issuer_raw.p;
+
+      ret = mbedtls_x509_get_serial( p, end_set, &signers_set->serial );
+      if ( ret != 0 )
+              return ( ret );
+
+      ret = pkcs7_get_digest_algorithm( p, end_set,
+                                      &signers_set->alg_identifier );
+      if ( ret != 0 )
+              return ( ret );
+
+      ret = pkcs7_get_digest_algorithm( p, end_set,
+                                      &signers_set->sig_alg_identifier );
+      if ( ret != 0 )
+              return ( ret );
+
+      ret = pkcs7_get_signature( p, end, &signers_set->sig );
+      if ( ret != 0 )
+              return ( ret );
+
+      signers_set->next = NULL;
+
+      return ( 0 );
+}
+
+/**
+ * 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;
+      size_t len = 0;
+      int ret;
+
+      ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
+                                             | MBEDTLS_ASN1_SEQUENCE );
+      if ( ret != 0 )
+              return ( MBEDTLS_ERR_PKCS7_INVALID_FORMAT + ret );
+
+      /* Get version of signed data */
+      ret = pkcs7_get_version( &p, end, &signed_data->version );
+      if ( ret != 0 )
+              return ( ret );
+
+      /* If version != 1, return invalid version */
+      if ( signed_data->version != MBEDTLS_PKCS7_SUPPORTED_VERSION ) {
+              mbedtls_printf("Invalid version\n");
+              return ( MBEDTLS_ERR_PKCS7_INVALID_VERSION );
+      }
+
+      /* Get digest algorithm */
+      ret = pkcs7_get_digest_algorithm_set( &p, end,
+                                          &signed_data->digest_alg_identifiers );
+      if ( ret != 0 ) {
+              mbedtls_printf("error getting digest algorithms\n");
+              return ( ret );
+      }
+
+      if ( signed_data->digest_alg_identifiers.len != strlen( MBEDTLS_OID_DIGEST_ALG_SHA256 ) )
+              return ( MBEDTLS_ERR_PKCS7_INVALID_ALG );
+
+      if ( memcmp( signed_data->digest_alg_identifiers.p, MBEDTLS_OID_DIGEST_ALG_SHA256,
+                 signed_data->digest_alg_identifiers.len ) ) {
+              mbedtls_fprintf(stdout, "Digest Algorithm other than SHA256 is not supported\n");
+              return ( MBEDTLS_ERR_PKCS7_INVALID_ALG );
+      }
+
+      /* Do not expect any content */
+      ret = pkcs7_get_content_info_type( &p, end, &signed_data->content.oid );
+      if ( ret != 0 )
+              return ( ret );
+
+      if ( memcmp( signed_data->content.oid.p, MBEDTLS_OID_PKCS7_DATA,
+                 signed_data->content.oid.len ) ) {
+              mbedtls_printf("Invalid PKCS7 data\n");
+              return ( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO ) ;
+      }
+
+      p = p + signed_data->content.oid.len;
+
+      ret = pkcs7_get_next_content_len( &p, end, &len );
+      if ( ret != 0 )
+              return ( ret ); 
+
+      /* Get certificates */
+      mbedtls_x509_crt_init( &signed_data->certs );
+      ret = pkcs7_get_certificates( &p, len, &signed_data->certs );
+      if ( ret != 0 )
+              return ( ret ) ;
+
+      p = p + len;
+
+      /* Get signers info */
+      ret = pkcs7_get_signers_info_set( &p, end, &signed_data->signers );
+      if ( ret != 0 )
+              return ( ret );
+
+      return ( ret );
+}
+
+int mbedtls_pkcs7_parse_der( const unsigned char *buf, const int buflen,
+                      mbedtls_pkcs7 *pkcs7 )
+{
+      unsigned char *start;
+      unsigned char *end;
+      size_t len = 0;
+      int ret;
+
+      /* use internal buffer for parsing */
+      start = ( unsigned char * )buf;
+      end = start + buflen;
+
+      if (!pkcs7)
+              return ( MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA );
+
+      ret = pkcs7_get_content_info_type( &start, end, &pkcs7->content_type_oid );
+      if ( ret != 0 )
+              goto out;
+
+      if ( ( !memcmp( pkcs7->content_type_oid.p, MBEDTLS_OID_PKCS7_DATA,
+                 pkcs7->content_type_oid.len ) )
+          || ( !memcmp( pkcs7->content_type_oid.p, MBEDTLS_OID_PKCS7_ENCRYPTED_DATA,
+                 pkcs7->content_type_oid.len ) )
+          || ( !memcmp(pkcs7->content_type_oid.p, MBEDTLS_OID_PKCS7_ENVELOPED_DATA,
+                 pkcs7->content_type_oid.len ) )
+            || ( !memcmp(pkcs7->content_type_oid.p, MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA,
+                 pkcs7->content_type_oid.len ) )
+            || ( !memcmp(pkcs7->content_type_oid.p, MBEDTLS_OID_PKCS7_DIGESTED_DATA,
+                 pkcs7->content_type_oid.len ) )
+          || ( !memcmp(pkcs7->content_type_oid.p, MBEDTLS_OID_PKCS7_ENCRYPTED_DATA,
+                 pkcs7->content_type_oid.len ) ) ) {
+              mbedtls_printf("Unsupported PKCS7 data type\n");
+              ret =  MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
+              goto out;
+      }
+
+      if ( ( memcmp( pkcs7->content_type_oid.p, MBEDTLS_OID_PKCS7_SIGNED_DATA,
+                 pkcs7->content_type_oid.len ) ) ) {
+               mbedtls_printf("Invalid PKCS7 data type\n");
+               ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
+               goto out;
+      }
+      mbedtls_printf("Content type is SignedData\n");
+
+      start = start + pkcs7->content_type_oid.len;
+
+      ret = pkcs7_get_next_content_len( &start, end, &len );
+      if ( ret != 0 )
+              goto out;
+
+      ret = pkcs7_get_signed_data( start, len, &pkcs7->signed_data );
+      if ( ret != 0 )
+              goto out;
+
+out:
+      return ( ret );
+}
+
+int mbedtls_pkcs7_signed_data_verify( mbedtls_pkcs7 *pkcs7, mbedtls_x509_crt *cert, const unsigned char *data, int datalen )
+{
+
+       int ret;
+       unsigned char hash[32];
+       mbedtls_pk_context pk_cxt = cert->pk;
+       const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 );
+
+       mbedtls_md( md_info, data, datalen, hash );
+       ret = mbedtls_pk_verify( &pk_cxt, MBEDTLS_MD_SHA256, hash, sizeof(hash), pkcs7->signed_data.signers.sig.p, pkcs7->signed_data.signers.sig.len );
+
+       mbedtls_printf("Verification return code is %04x\n", ret);
+
+       return ( ret );
+}
+
+/*
+ * Unallocate all pkcs7 data
+ */
+void mbedtls_pkcs7_free(  mbedtls_pkcs7 *pkcs7 )
+{
+	mbedtls_x509_name *name_cur;
+	mbedtls_x509_name *name_prv;
+
+	if (pkcs7 == NULL)
+		return;
+
+	mbedtls_x509_crt_free( &pkcs7->signed_data.certs );
+	mbedtls_x509_crl_free( &pkcs7->signed_data.crl );
+
+	name_cur = pkcs7->signed_data.signers.issuer.next;
+        while( name_cur != NULL )
+        {
+            name_prv = name_cur;
+            name_cur = name_cur->next;
+            mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
+            mbedtls_free( name_prv );
+        }
+}
+
+#endif
diff --git a/libstb/crypto/pkcs7/pkcs7.h b/libstb/crypto/pkcs7/pkcs7.h
new file mode 100644
index 00000000..7f14b4b8
--- /dev/null
+++ b/libstb/crypto/pkcs7/pkcs7.h
@@ -0,0 +1,151 @@ 
+/**
+ * \file pkcs7.h
+ *
+ * \brief PKCS7 generic defines and structures
+ */
+/*
+ *  Copyright (C) 2019,  IBM Corp, All Rights Reserved
+ *  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.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+#ifndef MBEDTLS_PKCS7_H
+#define MBEDTLS_PKCS7_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#include "mbedtls/asn1.h"
+#include "mbedtls/x509.h"
+#include "mbedtls/x509_crt.h"
+
+/**
+ * \name PKCS7 Error codes
+ * \{
+ */
+#define MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE              -0x7080  /**< Unavailable feature, e.g. anything other than signed data. */
+#define MBEDTLS_ERR_PKCS7_INVALID_FORMAT                   -0x7100  /**< The CRT/CRL format is invalid, e.g. different type expected. */
+#define MBEDTLS_ERR_PKCS7_INVALID_VERSION                  -0x7180  /**< The PKCS7 version element is invalid or cannot be parsed. */
+#define MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO             -0x7200  /**< The PKCS7 content info invalid or cannot be parsed. */
+#define MBEDTLS_ERR_PKCS7_INVALID_ALG                      -0x7280  /**< The algorithm tag or value is invalid or cannot be parsed. */
+#define MBEDTLS_ERR_PKCS7_INVALID_SIGNATURE                -0x7300  /**< Error parsing the signature */
+#define MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO              -0x7380  /**< Error parsing the signer's info */
+#define MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA                   -0x7400  /**< Input invalid. */
+#define MBEDTLS_ERR_PKCS7_ALLOC_FAILED                     -0x7480  /**< Allocation of memory failed. */
+#define MBEDTLS_ERR_PKCS7_FILE_IO_ERROR                    -0x7500  /**< File Read/Write Error */
+/* \} 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;
+
+/**
+ * Structure holding PKCS7 signer info
+ */
+typedef struct mbedtls_pkcs7_signer_info {
+        int version;
+        mbedtls_x509_buf serial;
+        mbedtls_x509_name issuer;
+        mbedtls_x509_buf issuer_raw;
+        mbedtls_x509_buf alg_identifier;
+        mbedtls_x509_buf sig_alg_identifier;
+        mbedtls_x509_buf sig;
+        struct mbedtls_pkcs7_signer_info *next;
+}
+mbedtls_pkcs7_signer_info;
+
+/**
+ * Structure holding attached data as part of PKCS7 signed data format
+ */
+typedef struct mbedtls_pkcs7_data {
+        mbedtls_pkcs7_buf oid;
+        mbedtls_pkcs7_buf data;
+}
+mbedtls_pkcs7_data;
+
+/**
+ * Structure holding the signed data section
+ */
+typedef struct mbedtls_pkcs7_signed_data {
+        int version;
+        mbedtls_pkcs7_buf digest_alg_identifiers;
+        struct mbedtls_pkcs7_data content;
+        mbedtls_x509_crt certs;
+        mbedtls_x509_crl crl;
+        struct mbedtls_pkcs7_signer_info signers;
+}
+mbedtls_pkcs7_signed_data;
+
+/**
+ * Structure holding PKCS7 structure, only signed data for now
+ */
+typedef struct mbedtls_pkcs7 {
+        mbedtls_pkcs7_buf content_type_oid;
+        struct mbedtls_pkcs7_signed_data signed_data;
+}
+mbedtls_pkcs7;
+
+void mbedtls_pkcs7_init( mbedtls_pkcs7 *pkcs7 );
+
+int mbedtls_pkcs7_parse_der(const unsigned char *buf, const int buflen, mbedtls_pkcs7 *pkcs7);
+
+int mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 *pkcs7, mbedtls_x509_crt *cert, const unsigned char *data, int datalen);
+
+int mbedtls_pkcs7_load_file( const char *path, unsigned char **buf, size_t *n );
+
+void mbedtls_pkcs7_free(  mbedtls_pkcs7 *pkcs7 );
+
+/*
+ * PKCS#7 OIDs
+ */
+#define MBEDTLS_OID_PKCS7				MBEDTLS_OID_PKCS "\x07" /**< pkcs-7 */
+#define MBEDTLS_OID_PKCS7_DATA				MBEDTLS_OID_PKCS7 "\x01" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */
+#define MBEDTLS_OID_PKCS7_SIGNED_DATA			MBEDTLS_OID_PKCS7 "\x02" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */
+#define MBEDTLS_OID_PKCS7_ENVELOPED_DATA		MBEDTLS_OID_PKCS7 "\x03" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */
+#define MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA	MBEDTLS_OID_PKCS7 "\x04" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */
+#define MBEDTLS_OID_PKCS7_DIGESTED_DATA			MBEDTLS_OID_PKCS7 "\x05" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */
+#define MBEDTLS_OID_PKCS7_ENCRYPTED_DATA		MBEDTLS_OID_PKCS7 "\x06" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* pkcs7.h */