/* Convert the various cipher NIDs and dummies to a proper OID NID */ int EVP_CIPHER_type(const EVP_CIPHER *ctx) { int nid; ASN1_OBJECT *otmp; nid = EVP_CIPHER_nid(ctx); switch (nid) { case NID_rc2_cbc: case NID_rc2_64_cbc: case NID_rc2_40_cbc: return NID_rc2_cbc; case NID_rc4: case NID_rc4_40: return NID_rc4; case NID_aes_128_cfb128: case NID_aes_128_cfb8: case NID_aes_128_cfb1: return NID_aes_128_cfb128; case NID_aes_192_cfb128: case NID_aes_192_cfb8: case NID_aes_192_cfb1: return NID_aes_192_cfb128; case NID_aes_256_cfb128: case NID_aes_256_cfb8: case NID_aes_256_cfb1: return NID_aes_256_cfb128; case NID_des_cfb64: case NID_des_cfb8: case NID_des_cfb1: return NID_des_cfb64; case NID_des_ede3_cfb64: case NID_des_ede3_cfb8: case NID_des_ede3_cfb1: return NID_des_cfb64; default: /* Check it has an OID and it is valid */ otmp = OBJ_nid2obj(nid); if (OBJ_get0_data(otmp) == NULL) nid = NID_undef; ASN1_OBJECT_free(otmp); return nid; } }
/** Verifies the validity of a PE/COFF Authenticode Signature as described in "Windows Authenticode Portable Executable Signature Format". If AuthData is NULL, then return FALSE. If ImageHash is NULL, then return FALSE. Caution: This function may receive untrusted input. PE/COFF Authenticode is external input, so this function will do basic check for Authenticode data structure. @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed PE/COFF image to be verified. @param[in] DataSize Size of the Authenticode Signature in bytes. @param[in] TrustedCert Pointer to a trusted/root certificate encoded in DER, which is used for certificate chain verification. @param[in] CertSize Size of the trusted certificate in bytes. @param[in] ImageHash Pointer to the original image file hash value. The procedure for calculating the image hash value is described in Authenticode specification. @param[in] HashSize Size of Image hash value in bytes. @retval TRUE The specified Authenticode Signature is valid. @retval FALSE Invalid Authenticode Signature. **/ BOOLEAN EFIAPI AuthenticodeVerify ( IN CONST UINT8 *AuthData, IN UINTN DataSize, IN CONST UINT8 *TrustedCert, IN UINTN CertSize, IN CONST UINT8 *ImageHash, IN UINTN HashSize ) { BOOLEAN Status; PKCS7 *Pkcs7; CONST UINT8 *Temp; CONST UINT8 *OrigAuthData; UINT8 *SpcIndirectDataContent; UINT8 Asn1Byte; UINTN ContentSize; CONST UINT8 *SpcIndirectDataOid; // // Check input parameters. // if ((AuthData == NULL) || (TrustedCert == NULL) || (ImageHash == NULL)) { return FALSE; } if ((DataSize > INT_MAX) || (CertSize > INT_MAX) || (HashSize > INT_MAX)) { return FALSE; } Status = FALSE; Pkcs7 = NULL; OrigAuthData = AuthData; // // Retrieve & Parse PKCS#7 Data (DER encoding) from Authenticode Signature // Temp = AuthData; Pkcs7 = d2i_PKCS7 (NULL, &Temp, (int)DataSize); if (Pkcs7 == NULL) { goto _Exit; } // // Check if it's PKCS#7 Signed Data (for Authenticode Scenario) // if (!PKCS7_type_is_signed (Pkcs7)) { goto _Exit; } // // NOTE: OpenSSL PKCS7 Decoder didn't work for Authenticode-format signed data due to // some authenticode-specific structure. Use opaque ASN.1 string to retrieve // PKCS#7 ContentInfo here. // SpcIndirectDataOid = OBJ_get0_data(Pkcs7->d.sign->contents->type); if (OBJ_length(Pkcs7->d.sign->contents->type) != sizeof(mSpcIndirectOidValue) || CompareMem ( SpcIndirectDataOid, mSpcIndirectOidValue, sizeof (mSpcIndirectOidValue) ) != 0) { // // Un-matched SPC_INDIRECT_DATA_OBJID. // goto _Exit; } SpcIndirectDataContent = (UINT8 *)(Pkcs7->d.sign->contents->d.other->value.asn1_string->data); // // Retrieve the SEQUENCE data size from ASN.1-encoded SpcIndirectDataContent. // Asn1Byte = *(SpcIndirectDataContent + 1); if ((Asn1Byte & 0x80) == 0) { // // Short Form of Length Encoding (Length < 128) // ContentSize = (UINTN) (Asn1Byte & 0x7F); // // Skip the SEQUENCE Tag; // SpcIndirectDataContent += 2; } else if ((Asn1Byte & 0x81) == 0x81) { // // Long Form of Length Encoding (128 <= Length < 255, Single Octet) // ContentSize = (UINTN) (*(UINT8 *)(SpcIndirectDataContent + 2)); // // Skip the SEQUENCE Tag; // SpcIndirectDataContent += 3; } else if ((Asn1Byte & 0x82) == 0x82) { // // Long Form of Length Encoding (Length > 255, Two Octet) // ContentSize = (UINTN) (*(UINT8 *)(SpcIndirectDataContent + 2)); ContentSize = (ContentSize << 8) + (UINTN)(*(UINT8 *)(SpcIndirectDataContent + 3)); // // Skip the SEQUENCE Tag; // SpcIndirectDataContent += 4; } else { goto _Exit; } // // Compare the original file hash value to the digest retrieve from SpcIndirectDataContent // defined in Authenticode // NOTE: Need to double-check HashLength here! // if (CompareMem (SpcIndirectDataContent + ContentSize - HashSize, ImageHash, HashSize) != 0) { // // Un-matched PE/COFF Hash Value // goto _Exit; } // // Verifies the PKCS#7 Signed Data in PE/COFF Authenticode Signature // Status = (BOOLEAN) Pkcs7Verify (OrigAuthData, DataSize, TrustedCert, CertSize, SpcIndirectDataContent, ContentSize); _Exit: // // Release Resources // PKCS7_free (Pkcs7); return Status; }