2020-11-16 20:03:12 +01:00
|
|
|
/* 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;
|
2020-12-14 23:44:49 +01:00
|
|
|
unsigned char *start = *p;
|
2020-11-16 20:03:12 +01:00
|
|
|
|
|
|
|
ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
|
|
|
|
| MBEDTLS_ASN1_SEQUENCE );
|
2021-07-01 21:29:50 +02:00
|
|
|
if( ret != 0 ) {
|
|
|
|
*p = start;
|
2020-11-16 20:03:12 +01:00
|
|
|
return( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO + ret );
|
2021-07-01 21:29:50 +02:00
|
|
|
}
|
2020-11-16 20:03:12 +01:00
|
|
|
|
|
|
|
ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_OID );
|
2020-12-14 23:44:49 +01:00
|
|
|
if( ret != 0 ) {
|
|
|
|
*p = start;
|
2020-11-16 20:03:12 +01:00
|
|
|
return( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO + ret );
|
2020-12-14 23:44:49 +01:00
|
|
|
}
|
2020-11-16 20:03:12 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2022-02-25 18:43:31 +01:00
|
|
|
ret = pkcs7_get_version( p, end_set, &signers_set->version );
|
2020-11-16 20:03:12 +01:00
|
|
|
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;
|
2020-12-14 23:44:49 +01:00
|
|
|
int isoidset = 0;
|
2020-11-16 20:03:12 +01:00
|
|
|
|
|
|
|
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 )
|
2020-12-14 23:44:49 +01:00
|
|
|
{
|
|
|
|
len = buflen;
|
|
|
|
goto try_data;
|
|
|
|
}
|
2020-11-16 20:03:12 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-12-14 23:44:49 +01:00
|
|
|
isoidset = 1;
|
2020-11-16 20:03:12 +01:00
|
|
|
start = start + pkcs7->content_type_oid.len;
|
|
|
|
|
|
|
|
ret = pkcs7_get_next_content_len( &start, end, &len );
|
|
|
|
if( ret != 0 )
|
|
|
|
goto out;
|
|
|
|
|
2020-12-14 23:44:49 +01:00
|
|
|
try_data:
|
2020-11-16 20:03:12 +01:00
|
|
|
ret = pkcs7_get_signed_data( start, len, &pkcs7->signed_data );
|
2020-12-14 23:44:49 +01:00
|
|
|
if ( ret != 0 )
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
if ( !isoidset )
|
|
|
|
{
|
|
|
|
pkcs7->content_type_oid.tag = MBEDTLS_ASN1_OID;
|
|
|
|
pkcs7->content_type_oid.len = MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS7_SIGNED_DATA );
|
|
|
|
pkcs7->content_type_oid.p = (unsigned char *)MBEDTLS_OID_PKCS7_SIGNED_DATA;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = MBEDTLS_PKCS7_SIGNED_DATA;
|
2020-11-16 20:03:12 +01:00
|
|
|
|
|
|
|
out:
|
2020-12-14 23:44:49 +01:00
|
|
|
if ( ret < 0 )
|
2020-11-16 20:03:12 +01:00
|
|
|
mbedtls_pkcs7_free( pkcs7 );
|
2020-12-14 23:44:49 +01:00
|
|
|
|
2020-11-16 20:03:12 +01:00
|
|
|
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 );
|
|
|
|
}
|
|
|
|
|
2022-02-23 00:19:59 +01:00
|
|
|
ret = mbedtls_md( md_info, data, datalen, hash );
|
|
|
|
if( ret != 0 )
|
|
|
|
{
|
|
|
|
mbedtls_free( hash );
|
|
|
|
return( ret );
|
|
|
|
}
|
2020-11-16 20:03:12 +01:00
|
|
|
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
|