mbedtls: add support for pkcs7

PKCS7 signing format is used by OpenPOWER Key Management, which is
using mbedtls as its crypto library.

This patch adds the limited support of pkcs7 parser and verification
to the mbedtls. The limitations are:

* Only signed data is supported.
* CRLs are not currently handled.
* Single signer is supported.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Signed-off-by: Eric Richter <erichte@linux.ibm.com>
Signed-off-by: Nayna Jain <nayna@linux.ibm.com>
This commit is contained in:
Nayna Jain 2020-11-16 19:03:12 +00:00 committed by Nick Child
parent e00d6d6b55
commit c9deb184b0
12 changed files with 1388 additions and 1 deletions

View file

@ -38,8 +38,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.
* \{
*/

View file

@ -989,6 +989,13 @@
#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) ) )
#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

View file

@ -95,6 +95,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)

View file

@ -2660,6 +2660,21 @@
*/
#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
*
* This module is required for the PKCS7 parsing modules.
*/
#define MBEDTLS_PKCS7_C
/**
* \def MBEDTLS_PKCS12_C
*

View file

@ -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 } */
@ -300,6 +301,16 @@
#define MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5 "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */
#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
*/

224
include/mbedtls/pkcs7.h Normal file
View file

@ -0,0 +1,224 @@
/**
* \file pkcs7.h
*
* \brief PKCS7 generic defines and structures
* https://tools.ietf.org/html/rfc2315
*/
/*
* 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)
*/
/**
* Note: For the time being, this application 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 MbedTLS is the signed data content type.
* - The only supported PKCS7 Signed Data syntax version is version 1
* - The RFC specifies support for BER. This application 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 MbedTLS.
* - The RFC specifies the Signed Data certificate format can be
* X509 or PKCS6. The only type currently supported in MbedTLS is X509.
* - The RFC specifies the Signed Data type can contain
* certificate-revocation lists (crls). This application has no support
* for crls so it is assumed to be an empty list.
* - The RFC specifies support for multiple signers. This application only
* supports the Signed Data type with a single signer.
*/
#ifndef MBEDTLS_PKCS7_H
#define MBEDTLS_PKCS7_H
#include "mbedtls/build_info.h"
#include "asn1.h"
#include "x509.h"
#include "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 -0x53F0 /**< 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 -0x54F0 /**< 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 -0x55F0 /**< 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 -0x56F0 /**< Error parsing the signer's info */
#define MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA -0x5700 /**< Input invalid. */
#define MBEDTLS_ERR_PKCS7_ALLOC_FAILED -0x57F0 /**< Allocation of memory failed. */
#define MBEDTLS_ERR_PKCS7_VERIFY_FAIL -0x5800 /**< Verification Failed */
/* \} 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;
int no_of_certs;
mbedtls_x509_crt certs;
int no_of_crls;
mbedtls_x509_crl crl;
int no_of_signers;
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 raw;
mbedtls_pkcs7_buf content_type_oid;
mbedtls_pkcs7_signed_data 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 \c 0, 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 */

View file

@ -165,6 +165,7 @@ OBJS_X509= \
x509_csr.o \
x509write_crt.o \
x509write_csr.o \
pkcs7.o \
# This line is intentionally left blank
OBJS_TLS= \

561
library/pkcs7.c Normal file
View file

@ -0,0 +1,561 @@
/* 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.
*/
#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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#if defined(MBEDTLS_FS_IO)
#include <sys/types.h>
#include <sys/stat.h>
#endif
#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
/**
* Initializes the pkcs7 structure.
*/
void mbedtls_pkcs7_init( mbedtls_pkcs7 *pkcs7 )
{
memset( pkcs7, 0, sizeof( mbedtls_pkcs7 ) );
pkcs7->raw.p = NULL;
}
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 );
/* If version != 1, return invalid version */
if( *ver != MBEDTLS_PKCS7_SUPPORTED_VERSION )
return( MBEDTLS_ERR_PKCS7_INVALID_VERSION );
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 != 0 )
return( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO + ret );
ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_OID );
if( ret != 0 )
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 );
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 != 0 )
return( MBEDTLS_ERR_PKCS7_INVALID_ALG + ret );
if ( *p != end )
return ( MBEDTLS_ERR_PKCS7_INVALID_FORMAT );
return( 0 );
}
/**
* 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;
size_t len1 = 0;
size_t len2 = 0;
unsigned char *end_set, *end_cert;
unsigned char *start = *p;
if( ( ret = mbedtls_asn1_get_tag( p, end, &len1, MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 )
{
if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
return( 0 );
return( MBEDTLS_ERR_PKCS7_INVALID_FORMAT + ret );
}
start = *p;
end_set = *p + len1;
ret = mbedtls_asn1_get_tag( p, end_set, &len2, MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE );
if( ret != 0 )
return( MBEDTLS_ERR_PKCS7_INVALID_CERT + ret );
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)
return ( MBEDTLS_ERR_PKCS7_INVALID_CERT );
*p = start;
if( ( ret = mbedtls_x509_crt_parse( certs, *p, len1 ) ) < 0 )
return( MBEDTLS_ERR_PKCS7_INVALID_CERT );
*p = *p + len1;
/* Since in this version we strictly support single certificate, and reaching
* here implies we have parsed successfully, we return 1. */
return( 1 );
}
/**
* 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( ret );
signature->tag = MBEDTLS_ASN1_OCTET_STRING;
signature->len = len;
signature->p = *p;
*p = *p + len;
return( 0 );
}
/**
* SignerInfos ::= SET of SignerInfo
* SignerInfo ::= SEQUENCE {
* version Version;
* issuerAndSerialNumber IssuerAndSerialNumber,
* digestAlgorithm DigestAlgorithmIdentifier,
* authenticatedAttributes
* [0] IMPLICIT Attributes OPTIONAL,
* digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
* encryptedDigest EncryptedDigest,
* unauthenticatedAttributes
* [1] IMPLICIT Attributes OPTIONAL,
* 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, *end_set_signer;
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 );
end_set_signer = *p + len;
if (end_set_signer != end_set)
return ( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO );
end_set = end_set_signer;
ret = mbedtls_asn1_get_int( p, end_set, &signers_set->version );
if( ret != 0 )
return( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO );
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 );
/* Parsing IssuerAndSerialNumber */
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( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO );
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( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO );
ret = pkcs7_get_digest_algorithm( p, end_set, &signers_set->alg_identifier );
if( ret != 0 )
return( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO );
ret = pkcs7_get_digest_algorithm( p, end_set, &signers_set->sig_alg_identifier );
if( ret != 0 )
return( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO );
ret = pkcs7_get_signature( p, end_set, &signers_set->sig );
if( ret != 0 )
return( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO );
signers_set->next = NULL;
if (*p != end_set)
return ( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO );
/* Since in this version we strictly support single signer, and reaching
* here implies we have parsed successfully, we return 1. */
return( 1 );
}
/**
* 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_md_type_t md_alg;
ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE );
if( ret != 0 )
return( MBEDTLS_ERR_PKCS7_INVALID_FORMAT + ret );
end_set = p + len;
/* Get version of signed data */
ret = pkcs7_get_version( &p, end_set, &signed_data->version );
if( ret != 0 )
return( ret );
/* Get digest algorithm */
ret = pkcs7_get_digest_algorithm_set( &p, end_set,
&signed_data->digest_alg_identifiers );
if( ret != 0 )
return( ret );
ret = mbedtls_oid_get_md_alg( &signed_data->digest_alg_identifiers, &md_alg );
if( ret != 0 )
return( MBEDTLS_ERR_PKCS7_INVALID_ALG );
/* Do not expect any content */
ret = pkcs7_get_content_info_type( &p, end_set, &signed_data->content.oid );
if( ret != 0 )
return( ret );
if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_DATA, &signed_data->content.oid ) )
{
return( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO ) ;
}
p = p + signed_data->content.oid.len;
/* 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 )
return( ret ) ;
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 )
return( ret );
signed_data->no_of_signers = ret;
/* Support single signer */
if ( p != end )
ret = MBEDTLS_ERR_PKCS7_INVALID_FORMAT;
ret = 0;
return( ret );
}
int mbedtls_pkcs7_parse_der( mbedtls_pkcs7 *pkcs7, const unsigned char *buf,
const size_t buflen )
{
unsigned char *start;
unsigned char *end;
size_t len = 0;
int ret;
if( !pkcs7 )
return( MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA );
/* make an internal copy of the buffer for parsing */
pkcs7->raw.p = start = mbedtls_calloc( 1, buflen );
if( pkcs7->raw.p == NULL )
{
return( MBEDTLS_ERR_PKCS7_ALLOC_FAILED );
}
memcpy( start, buf, buflen );
pkcs7->raw.len = buflen;
end = start + buflen;
ret = pkcs7_get_content_info_type( &start, end, &pkcs7->content_type_oid );
if( ret != 0 )
goto out;
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;
}
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 );
out:
if ( ret != 0 )
mbedtls_pkcs7_free( pkcs7 );
return( ret );
}
int mbedtls_pkcs7_signed_data_verify( mbedtls_pkcs7 *pkcs7,
const mbedtls_x509_crt *cert,
const unsigned char *data,
size_t datalen )
{
int ret;
unsigned char *hash;
mbedtls_pk_context pk_cxt = cert->pk;
const mbedtls_md_info_t *md_info;
mbedtls_md_type_t md_alg;
ret = mbedtls_oid_get_md_alg( &pkcs7->signed_data.digest_alg_identifiers, &md_alg );
if( ret != 0 )
return( MBEDTLS_ERR_PKCS7_VERIFY_FAIL );
md_info = mbedtls_md_info_from_type( md_alg );
hash = mbedtls_calloc( mbedtls_md_get_size( md_info ), 1 );
if( hash == NULL ) {
return( MBEDTLS_ERR_PKCS7_ALLOC_FAILED );
}
mbedtls_md( md_info, data, datalen, hash );
ret = mbedtls_pk_verify( &pk_cxt, md_alg, hash, 0,
pkcs7->signed_data.signers.sig.p,
pkcs7->signed_data.signers.sig.len );
mbedtls_free( hash );
return( ret );
}
int mbedtls_pkcs7_signed_hash_verify( mbedtls_pkcs7 *pkcs7,
const mbedtls_x509_crt *cert,
const unsigned char *hash, size_t hashlen)
{
int ret;
mbedtls_md_type_t md_alg;
mbedtls_pk_context pk_cxt;
ret = mbedtls_oid_get_md_alg( &pkcs7->signed_data.digest_alg_identifiers, &md_alg );
if( ret != 0 )
return( MBEDTLS_ERR_PKCS7_VERIFY_FAIL );
pk_cxt = cert->pk;
ret = mbedtls_pk_verify( &pk_cxt, md_alg, hash, hashlen,
pkcs7->signed_data.signers.sig.p,
pkcs7->signed_data.signers.sig.len );
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 || 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 );
name_cur = pkcs7->signed_data.signers.issuer.next;
while( name_cur != NULL )
{
name_prv = name_cur;
name_cur = name_cur->next;
mbedtls_free( name_prv );
}
pkcs7->raw.p = NULL;
}
#endif

View file

@ -306,6 +306,7 @@ def include_in_crypto(name):
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

View file

@ -1131,6 +1131,98 @@ ecdsa_secp521r1.crt: ecdsa_secp521r1.csr
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.txt
# 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
# Generate data file to be signed
pkcs7_data.txt:
echo "Hello" > $@
echo 2 >> pkcs7_data_1.txt
all_final += pkcs7_data.txt
# Generate another data file to check hash mismatch during certificate verification
pkcs7_data_1.txt: $(pkcs7_test_file)
cat $(pkcs7_test_file) > $@
echo 2 >> $@
all_final += pkcs7_data_1.txt
# 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.txt -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.txt -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.txt -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.txt -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.txt -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.txt -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.txt -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
################################################################
#### Diffie-Hellman parameters
################################################################

View file

@ -0,0 +1,53 @@
PKCS7 Signed Data Parse Pass SHA256 #1
pkcs7_parse:"data_files/pkcs7_data_cert_signed_sha256.der"
PKCS7 Signed Data Parse Pass SHA1 #2
depends_on:MBEDTLS_SHA1_C
pkcs7_parse:"data_files/pkcs7_data_cert_signed_sha1.der"
PKCS7 Signed Data Parse Pass Without CERT #3
pkcs7_parse_without_cert:"data_files/pkcs7_data_without_cert_signed.der"
PKCS7 Signed Data Parse Fail with multiple signers #4
pkcs7_parse_multiple_signers:"data_files/pkcs7_data_multiple_signed.der"
PKCS7 Signed Data Parse Fail with multiple certs #4
pkcs7_parse_multiple_signers:"data_files/pkcs7_data_multiple_certs_signed.der"
PKCS7 Signed Data Parse Fail with corrupted cert #5
pkcs7_parse_corrupted_cert:"data_files/pkcs7_data_signed_badcert.der"
PKCS7 Signed Data Parse Fail with corrupted signer info #6
pkcs7_parse_corrupted_signer_info:"data_files/pkcs7_data_signed_badsigner.der"
PKCS7 Signed Data Parse Fail Version other than 1 #7
pkcs7_parse_version:"data_files/pkcs7_data_cert_signed_v2.der"
PKCS7 Signed Data Parse Fail Encrypted Content #8
pkcs7_parse_content_oid:"data_files/pkcs7_data_cert_encrypted.der"
PKCS7 Signed Data Verification Pass SHA256 #9
pkcs7_verify:"data_files/pkcs7_data_cert_signed_sha256.der":"data_files/pkcs7-rsa-sha256-1.crt":"data_files/pkcs7_data.txt"
PKCS7 Signed Data Verification Pass SHA256 #9.1
pkcs7_verify_hash:"data_files/pkcs7_data_cert_signed_sha256.der":"data_files/pkcs7-rsa-sha256-1.crt":"data_files/pkcs7_data.txt"
PKCS7 Signed Data Verification Pass SHA1 #10
depends_on:MBEDTLS_SHA1_C
pkcs7_verify:"data_files/pkcs7_data_cert_signed_sha1.der":"data_files/pkcs7-rsa-sha256-1.crt":"data_files/pkcs7_data.txt"
PKCS7 Signed Data Verification Pass SHA512 #11
depends_on:MBEDTLS_SHA512_C
pkcs7_verify:"data_files/pkcs7_data_cert_signed_sha512.der":"data_files/pkcs7-rsa-sha256-1.crt":"data_files/pkcs7_data.txt"
PKCS7 Signed Data Verification Fail because of different certificate #12
pkcs7_verify_badcert:"data_files/pkcs7_data_cert_signed_sha256.der":"data_files/pkcs7-rsa-sha256-2.crt":"data_files/pkcs7_data.txt"
PKCS7 Signed Data Verification Fail because of different data hash #13
pkcs7_verify_tampered_data:"data_files/pkcs7_data_cert_signed_sha256.der":"data_files/pkcs7-rsa-sha256-1.crt":"data_files/pkcs7_data_1.txt"
PKCS7 Signed Data Parse Failure Corrupt signerInfo.issuer #15.1
pkcs7_parse_failure:"data_files/pkcs7_signerInfo_issuer_invalid_size.der"
PKCS7 Signed Data Parse Failure Corrupt signerInfo.serial #15.2
pkcs7_parse_failure:"data_files/pkcs7_signerInfo_serial_invalid_size.der"

View file

@ -0,0 +1,420 @@
/* 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_FS_IO
* END_DEPENDENCIES
*/
/* BEGIN_CASE depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA256_C */
void pkcs7_parse( char *pkcs7_file )
{
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 == 0 );
exit:
mbedtls_free( pkcs7_buf );
mbedtls_pkcs7_free( &pkcs7 );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_SHA256_C*/
void pkcs7_parse_without_cert( char *pkcs7_file )
{
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 == 0 );
exit:
mbedtls_free( pkcs7_buf );
mbedtls_pkcs7_free( &pkcs7 );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA256_C */
void pkcs7_parse_multiple_signers( char *pkcs7_file )
{
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 < 0 );
switch ( res ){
case MBEDTLS_ERR_PKCS7_INVALID_CERT:
TEST_ASSERT( res == MBEDTLS_ERR_PKCS7_INVALID_CERT );
break;
case MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO:
TEST_ASSERT( res == MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO );
break;
default:
TEST_ASSERT(0);
}
exit:
mbedtls_free( pkcs7_buf );
mbedtls_pkcs7_free( &pkcs7 );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA256_C */
void pkcs7_parse_corrupted_cert( char *pkcs7_file )
{
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 == MBEDTLS_ERR_PKCS7_INVALID_CERT );
exit:
mbedtls_free( pkcs7_buf );
mbedtls_pkcs7_free( &pkcs7 );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA256_C */
void pkcs7_parse_corrupted_signer_info( char *pkcs7_file )
{
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 < 0 );
exit:
mbedtls_free( pkcs7_buf );
mbedtls_pkcs7_free( &pkcs7 );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_SHA256_C */
void pkcs7_parse_version( char *pkcs7_file )
{
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 == MBEDTLS_ERR_PKCS7_INVALID_VERSION );
exit:
mbedtls_free( pkcs7_buf );
mbedtls_pkcs7_free( &pkcs7 );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_SHA256_C */
void pkcs7_parse_content_oid( char *pkcs7_file )
{
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 != 0 );
TEST_ASSERT( res == MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE );
exit:
mbedtls_free( pkcs7_buf );
mbedtls_pkcs7_free( &pkcs7 );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_X509_CRT_PARSE_C:MBEDTLS_PKCS1_V15:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA256_C */
void pkcs7_verify( char *pkcs7_file, char *crt, char *filetobesigned )
{
unsigned char *pkcs7_buf = NULL;
size_t buflen;
unsigned char *data = NULL;
struct stat st;
size_t datalen;
int res;
FILE *file;
mbedtls_pkcs7 pkcs7;
mbedtls_x509_crt x509;
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 == 0 );
mbedtls_free( pkcs7_buf );
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 );
buflen = fread( ( void * )data , sizeof( unsigned char ), datalen, file );
TEST_ASSERT( buflen == datalen);
fclose(file);
res = mbedtls_pkcs7_signed_data_verify( &pkcs7, &x509, data, datalen );
TEST_ASSERT( res == 0 );
exit:
mbedtls_x509_crt_free( &x509 );
mbedtls_free( data );
mbedtls_pkcs7_free( &pkcs7 );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_X509_CRT_PARSE_C:MBEDTLS_PKCS1_V15:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA256_C */
void pkcs7_verify_hash( char *pkcs7_file, char *crt, char *filetobesigned )
{
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;
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 == 0 );
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 );
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 );
mbedtls_md( md_info, data, datalen, hash );
res = mbedtls_pkcs7_signed_hash_verify( &pkcs7, &x509, hash, sizeof(hash));
TEST_ASSERT( res == 0 );
exit:
mbedtls_x509_crt_free( &x509 );
mbedtls_free( data );
mbedtls_pkcs7_free( &pkcs7 );
mbedtls_free( pkcs7_buf );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_X509_CRT_PARSE_C:MBEDTLS_PKCS1_V15:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA256_C */
void pkcs7_verify_badcert( char *pkcs7_file, char *crt, char *filetobesigned )
{
unsigned char *pkcs7_buf = NULL;
size_t buflen;
unsigned char *data = NULL;
struct stat st;
size_t datalen;
int res;
FILE *file;
mbedtls_pkcs7 pkcs7;
mbedtls_x509_crt x509;
mbedtls_pkcs7_init( &pkcs7 );
mbedtls_x509_crt_init( &x509 );
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 == 0 );
res = mbedtls_x509_crt_parse_file( &x509, crt );
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 = mbedtls_calloc( datalen, 1 );
buflen = fread( ( void * )data , sizeof( unsigned char ), datalen, file );
TEST_ASSERT( buflen == datalen);
fclose(file);
res = mbedtls_pkcs7_signed_data_verify( &pkcs7, &x509, data, datalen );
TEST_ASSERT( res != 0 );
exit:
mbedtls_x509_crt_free( &x509 );
mbedtls_free( data );
mbedtls_pkcs7_free( &pkcs7 );
mbedtls_free( pkcs7_buf );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_X509_CRT_PARSE_C:MBEDTLS_PKCS1_V15:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA256_C */
void pkcs7_verify_tampered_data( char *pkcs7_file, char *crt, char *filetobesigned )
{
unsigned char *pkcs7_buf = NULL;
size_t buflen;
unsigned char *data = NULL;
struct stat st;
size_t datalen;
int res;
FILE *file;
mbedtls_pkcs7 pkcs7;
mbedtls_x509_crt x509;
mbedtls_pkcs7_init( &pkcs7 );
mbedtls_x509_crt_init( &x509 );
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 == 0 );
res = mbedtls_x509_crt_parse_file( &x509, crt );
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 = mbedtls_calloc( datalen, 1 );
buflen = fread( ( void * )data , sizeof( unsigned char ), datalen, file );
TEST_ASSERT( buflen == datalen);
fclose(file);
res = mbedtls_pkcs7_signed_data_verify( &pkcs7, &x509, data, datalen );
TEST_ASSERT( res != 0 );
exit:
mbedtls_x509_crt_free( &x509 );
mbedtls_pkcs7_free( &pkcs7 );
mbedtls_free( data );
mbedtls_free( pkcs7_buf );
}
/* END_CASE */
/* BEGIN_CASE */
void pkcs7_parse_failure( char *pkcs7_file )
{
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 != 0 );
exit:
mbedtls_free( pkcs7_buf );
mbedtls_pkcs7_free( &pkcs7 );
}
/* END_CASE */