/** @file Non-runtime specific implementation of PKCS#7 SignedData Verification Wrapper. Copyright (c) 2019, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "InternalCryptLib.h" #include #include #include #include /** Check the contents of PKCS7 is not data. It is copied from PKCS7_type_is_other() in pk7_doit.c. @param[in] P7 Pointer to the location at which the PKCS7 is located. @retval TRUE If the type is others. @retval FALSE If the type is expected. **/ STATIC BOOLEAN Pkcs7TypeIsOther ( IN PKCS7 *P7 ) { BOOLEAN Others; INTN Nid = OBJ_obj2nid (P7->type); switch (Nid) { case NID_pkcs7_data: case NID_pkcs7_signed: case NID_pkcs7_enveloped: case NID_pkcs7_signedAndEnveloped: case NID_pkcs7_encrypted: Others = FALSE; break; default: Others = TRUE; } return Others; } /** Get the ASN.1 string for the PKCS7. It is copied from PKCS7_get_octet_string() in pk7_doit.c. @param[in] P7 Pointer to the location at which the PKCS7 is located. @return ASN1_OCTET_STRING ASN.1 string. **/ STATIC ASN1_OCTET_STRING* Pkcs7GetOctetString ( IN PKCS7 *P7 ) { if (PKCS7_type_is_data (P7)) { return P7->d.data; } if (Pkcs7TypeIsOther(P7) && (P7->d.other != NULL) && (P7->d.other->type == V_ASN1_OCTET_STRING)) { return P7->d.other->value.octet_string; } return NULL; } /** Extracts the attached content from a PKCS#7 signed data if existed. The input signed data could be wrapped in a ContentInfo structure. If P7Data, Content, or ContentSize is NULL, then return FALSE. If P7Length overflow, then return FALSE. If the P7Data is not correctly formatted, then return FALSE. Caution: This function may receive untrusted input. So this function will do basic check for PKCS#7 data structure. @param[in] P7Data Pointer to the PKCS#7 signed data to process. @param[in] P7Length Length of the PKCS#7 signed data in bytes. @param[out] Content Pointer to the extracted content from the PKCS#7 signedData. It's caller's responsibility to free the buffer with FreePool(). @param[out] ContentSize The size of the extracted content in bytes. @retval TRUE The P7Data was correctly formatted for processing. @retval FALSE The P7Data was not correctly formatted for processing. **/ BOOLEAN EFIAPI Pkcs7GetAttachedContent ( IN CONST UINT8 *P7Data, IN UINTN P7Length, OUT VOID **Content, OUT UINTN *ContentSize ) { BOOLEAN Status; PKCS7 *Pkcs7; UINT8 *SignedData; UINTN SignedDataSize; BOOLEAN Wrapped; CONST UINT8 *Temp; ASN1_OCTET_STRING *OctStr; // // Check input parameter. // if ((P7Data == NULL) || (P7Length > INT_MAX) || (Content == NULL) || (ContentSize == NULL)) { return FALSE; } *Content = NULL; Pkcs7 = NULL; SignedData = NULL; OctStr = NULL; Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &SignedData, &SignedDataSize); if (!Status || (SignedDataSize > INT_MAX)) { goto _Exit; } Status = FALSE; // // Decoding PKCS#7 SignedData // Temp = SignedData; Pkcs7 = d2i_PKCS7 (NULL, (const unsigned char **)&Temp, (int)SignedDataSize); if (Pkcs7 == NULL) { goto _Exit; } // // The type of Pkcs7 must be signedData // if (!PKCS7_type_is_signed (Pkcs7)) { goto _Exit; } // // Check for detached or attached content // if (PKCS7_get_detached (Pkcs7)) { // // No Content supplied for PKCS7 detached signedData // *Content = NULL; *ContentSize = 0; } else { // // Retrieve the attached content in PKCS7 signedData // OctStr = Pkcs7GetOctetString (Pkcs7->d.sign->contents); if (OctStr == NULL) { goto _Exit; } if ((OctStr->length > 0) && (OctStr->data != NULL)) { *ContentSize = OctStr->length; *Content = AllocatePool (*ContentSize); if (*Content == NULL) { *ContentSize = 0; goto _Exit; } CopyMem (*Content, OctStr->data, *ContentSize); } } Status = TRUE; _Exit: // // Release Resources // PKCS7_free (Pkcs7); if (!Wrapped) { OPENSSL_free (SignedData); } return Status; }