From patchwork Mon May 11 21:31:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Richter X-Patchwork-Id: 1288093 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49LZ5w5kLSz9sRf for ; Tue, 12 May 2020 07:37:24 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.ibm.com Received: from bilbo.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 49LZ5w2ZmdzDrBg for ; Tue, 12 May 2020 07:37:24 +1000 (AEST) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=linux.ibm.com (client-ip=148.163.156.1; helo=mx0a-001b2d01.pphosted.com; envelope-from=erichte@linux.ibm.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.ibm.com Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 49LYzz3D1GzDqjY for ; Tue, 12 May 2020 07:32:15 +1000 (AEST) Received: from pps.filterd (m0098409.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 04BLCGie025288 for ; Mon, 11 May 2020 17:32:13 -0400 Received: from ppma01fra.de.ibm.com (46.49.7a9f.ip4.static.sl-reverse.com [159.122.73.70]) by mx0a-001b2d01.pphosted.com with ESMTP id 30ws5easjy-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Mon, 11 May 2020 17:32:13 -0400 Received: from pps.filterd (ppma01fra.de.ibm.com [127.0.0.1]) by ppma01fra.de.ibm.com (8.16.0.27/8.16.0.27) with SMTP id 04BLPwnB005547 for ; Mon, 11 May 2020 21:32:11 GMT Received: from b06cxnps4076.portsmouth.uk.ibm.com (d06relay13.portsmouth.uk.ibm.com [9.149.109.198]) by ppma01fra.de.ibm.com with ESMTP id 30wm55a370-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Mon, 11 May 2020 21:32:11 +0000 Received: from b06wcsmtp001.portsmouth.uk.ibm.com (b06wcsmtp001.portsmouth.uk.ibm.com [9.149.105.160]) by b06cxnps4076.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 04BLW8I750593796 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 11 May 2020 21:32:08 GMT Received: from b06wcsmtp001.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 4CE5EA4060; Mon, 11 May 2020 21:32:08 +0000 (GMT) Received: from b06wcsmtp001.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id A2233A405B; Mon, 11 May 2020 21:32:07 +0000 (GMT) Received: from ceres.ibmuc.com (unknown [9.80.226.245]) by b06wcsmtp001.portsmouth.uk.ibm.com (Postfix) with ESMTP; Mon, 11 May 2020 21:32:07 +0000 (GMT) From: Eric Richter To: skiboot@lists.ozlabs.org Date: Mon, 11 May 2020 16:31:49 -0500 Message-Id: <20200511213152.24952-16-erichte@linux.ibm.com> X-Mailer: git-send-email 2.21.1 In-Reply-To: <20200511213152.24952-1-erichte@linux.ibm.com> References: <20200511213152.24952-1-erichte@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.216, 18.0.676 definitions=2020-05-11_10:2020-05-11, 2020-05-11 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 suspectscore=0 phishscore=0 spamscore=0 impostorscore=0 malwarescore=0 mlxlogscore=999 lowpriorityscore=0 bulkscore=0 adultscore=0 priorityscore=1501 mlxscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2005110159 Subject: [Skiboot] [PATCH v4 15/18] crypto: add out-of-tree mbedtls pkcs7 parser X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: nayna@linux.ibm.com Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" From: Nayna Jain 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 Signed-off-by: Eric Richter --- 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='' + +$(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 +#include +#include +#if defined(MBEDTLS_FS_IO) +#include +#include +#endif +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" +#else +#include +#include +#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 +#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 */