LIEF/api/python/PE/objects/signature/pySignerInfo.cpp

160 lines
5.4 KiB
C++
Raw Normal View History

2017-03-30 16:56:49 +02:00
/* Copyright 2017 R. Thomas
* Copyright 2017 Quarkslab
*
* 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 <string>
#include <sstream>
#include "LIEF/PE/hash.hpp"
2017-03-30 16:56:49 +02:00
#include "LIEF/PE/signature/SignerInfo.hpp"
#include "pyPE.hpp"
2018-06-08 14:58:00 +02:00
namespace LIEF {
namespace PE {
2017-03-30 16:56:49 +02:00
template<class T>
using getter_t = T (SignerInfo::*)(void) const;
template<class T>
using setter_t = void (SignerInfo::*)(T);
2018-06-08 14:58:00 +02:00
template<>
void create<SignerInfo>(py::module& m) {
2017-03-30 16:56:49 +02:00
2021-01-08 06:41:11 +01:00
py::class_<SignerInfo, LIEF::Object>(m, "SignerInfo",
R"delim(
SignerInfo as described in the `RFC 2315 #Section 9.2 <https://tools.ietf.org/html/rfc2315#section-9.2>`_
.. code-block:: text
SignerInfo ::= SEQUENCE {
version Version,
issuerAndSerialNumber IssuerAndSerialNumber,
digestAlgorithm DigestAlgorithmIdentifier,
authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
encryptedDigest EncryptedDigest,
unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
}
EncryptedDigest ::= OCTET STRING
)delim")
2017-03-30 16:56:49 +02:00
.def_property_readonly("version",
&SignerInfo::version,
"Should be 1")
2021-01-05 19:26:10 +01:00
.def_property_readonly("serial_number",
[] (const SignerInfo& info) -> py::bytes {
const std::vector<uint8_t>& data = info.serial_number();
return py::bytes(reinterpret_cast<const char*>(data.data()), data.size());
},
2021-01-08 06:41:11 +01:00
"The X509 serial number used to sign the signed-data (see: :attr:`lief.PE.x509.serial_number`)")
2021-01-05 19:26:10 +01:00
2017-03-30 16:56:49 +02:00
.def_property_readonly("issuer",
Authenticode-related bug fixes and improvements Part of Authenticode verification consists of: - Comparing the computed Authenticode hash to the digest stored in the ContentInfo section - Comparing hash(ContentInfo) to the digest stored in the AuthenticatedAttributes section - Verifying signed(hash(AuthenticatedAttributes)) using a certificate identified by the issuer and serial number specified in the SignerInfo section This commit makes it so that the raw bytes needed to calculate hash(ContentInfo) and hash(AuthenticatedAttributes) are available for use. ============================================================ Allow missing [0] in SpcSpOpusInfo Some executables have MoreInfo but not a ProgramName (and the documentation lists both as OPTIONAL), so handle this case correctly. Example: ``` 01416b1730218454c99b13592650cb170402b86742b4bab971565903b841829b SEQUENCE(2 elem) OBJECT IDENTIFIER1.3.6.1.4.1.311.2.1.12spcSpOpusInfo(Microsoft code signing) SET(1 elem) SEQUENCE(1 elem) [1](1 elem) [0]http://www.mozilla.com ``` ============================================================ Improve consistency of parsed serial numbers When parsing the issuer serial number, call mbedtls_x509_get_serial instead of parsing it as an integer directly with mbedtls_asn1_get_mpi. These two functions differ in how they treat serial numbers prepended with '00' to prevent them from being negative (the former preserves the '00', and the latter discards it). The embedded certs are parsed via a call to mbedtls_x509_crt_parse_der, which uses mbedtls_x509_get_serial behind the scenes, so there was an inconsistency between lief_obj.signature.signer_info.issuer[1] and lief_obj.signature.certificates[x].serial_number. Example: 8bf57d97dd917c4f823659266caaa33e7398406daf11ba8318e3f7414ee3fb24 ============================================================ Handle SpcLink and SpcString CHOICEs in SpcSpOpusInfo The Authenticode spec doc says that these can be CHOICES, so handle the easy ones and safely skip the others. ============================================================ Allow Authenticode sig to be parsed even if cert parsing fails By default, mbedtls doesn't support MD2 certs, which are fairly common in older signed executables. Ex: 1cb16f94cebdcad7dd05c8537375a6ff6379fcdb08528fc83889f26efaa84e2a ============================================================ Enable mbed TLS MD2 and MD4 support; add Unix debug options By default, mbedtls doesn't support MD2 certs, which are fairly common in older signed executables. Ex: 1cb16f94cebdcad7dd05c8537375a6ff6379fcdb08528fc83889f26efaa84e2a ============================================================ Set MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION flag Some older signed executables use certs with the SpcSpAgencyInfo Critical Extension, which mbed TLS doesn't support, so set MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION to have it skip this extension. Example: 781ca31416ec708a587851dafd90c661b86f244ab8b8475c4185e958e54ff838 ============================================================ Support accessing non-utf8 issuer names via Python For a few signatures where the issuer name contained non-utf8 characters, accessing the issuer name field in Python would raise a UnicodeDecodeError exception. Now this field is handled the same way the names in the individual certs are (I'm not sure if they get represented 100% correctly, but at least they are consistent, which is good enough for me). Example: 048f91b9302c88380fc66adac1e314d82733089ef3a31eadca5f0cb4169b195f
2019-07-26 17:51:14 -04:00
[] (const SignerInfo& object) {
2021-01-05 19:26:10 +01:00
return safe_string_converter(object.issuer());
Authenticode-related bug fixes and improvements Part of Authenticode verification consists of: - Comparing the computed Authenticode hash to the digest stored in the ContentInfo section - Comparing hash(ContentInfo) to the digest stored in the AuthenticatedAttributes section - Verifying signed(hash(AuthenticatedAttributes)) using a certificate identified by the issuer and serial number specified in the SignerInfo section This commit makes it so that the raw bytes needed to calculate hash(ContentInfo) and hash(AuthenticatedAttributes) are available for use. ============================================================ Allow missing [0] in SpcSpOpusInfo Some executables have MoreInfo but not a ProgramName (and the documentation lists both as OPTIONAL), so handle this case correctly. Example: ``` 01416b1730218454c99b13592650cb170402b86742b4bab971565903b841829b SEQUENCE(2 elem) OBJECT IDENTIFIER1.3.6.1.4.1.311.2.1.12spcSpOpusInfo(Microsoft code signing) SET(1 elem) SEQUENCE(1 elem) [1](1 elem) [0]http://www.mozilla.com ``` ============================================================ Improve consistency of parsed serial numbers When parsing the issuer serial number, call mbedtls_x509_get_serial instead of parsing it as an integer directly with mbedtls_asn1_get_mpi. These two functions differ in how they treat serial numbers prepended with '00' to prevent them from being negative (the former preserves the '00', and the latter discards it). The embedded certs are parsed via a call to mbedtls_x509_crt_parse_der, which uses mbedtls_x509_get_serial behind the scenes, so there was an inconsistency between lief_obj.signature.signer_info.issuer[1] and lief_obj.signature.certificates[x].serial_number. Example: 8bf57d97dd917c4f823659266caaa33e7398406daf11ba8318e3f7414ee3fb24 ============================================================ Handle SpcLink and SpcString CHOICEs in SpcSpOpusInfo The Authenticode spec doc says that these can be CHOICES, so handle the easy ones and safely skip the others. ============================================================ Allow Authenticode sig to be parsed even if cert parsing fails By default, mbedtls doesn't support MD2 certs, which are fairly common in older signed executables. Ex: 1cb16f94cebdcad7dd05c8537375a6ff6379fcdb08528fc83889f26efaa84e2a ============================================================ Enable mbed TLS MD2 and MD4 support; add Unix debug options By default, mbedtls doesn't support MD2 certs, which are fairly common in older signed executables. Ex: 1cb16f94cebdcad7dd05c8537375a6ff6379fcdb08528fc83889f26efaa84e2a ============================================================ Set MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION flag Some older signed executables use certs with the SpcSpAgencyInfo Critical Extension, which mbed TLS doesn't support, so set MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION to have it skip this extension. Example: 781ca31416ec708a587851dafd90c661b86f244ab8b8475c4185e958e54ff838 ============================================================ Support accessing non-utf8 issuer names via Python For a few signatures where the issuer name contained non-utf8 characters, accessing the issuer name field in Python would raise a UnicodeDecodeError exception. Now this field is handled the same way the names in the individual certs are (I'm not sure if they get represented 100% correctly, but at least they are consistent, which is good enough for me). Example: 048f91b9302c88380fc66adac1e314d82733089ef3a31eadca5f0cb4169b195f
2019-07-26 17:51:14 -04:00
},
2021-01-08 06:41:11 +01:00
"The X509 issuer used to sign the signed-data (see: :attr:`lief.PE.x509.issuer`)",
Authenticode-related bug fixes and improvements Part of Authenticode verification consists of: - Comparing the computed Authenticode hash to the digest stored in the ContentInfo section - Comparing hash(ContentInfo) to the digest stored in the AuthenticatedAttributes section - Verifying signed(hash(AuthenticatedAttributes)) using a certificate identified by the issuer and serial number specified in the SignerInfo section This commit makes it so that the raw bytes needed to calculate hash(ContentInfo) and hash(AuthenticatedAttributes) are available for use. ============================================================ Allow missing [0] in SpcSpOpusInfo Some executables have MoreInfo but not a ProgramName (and the documentation lists both as OPTIONAL), so handle this case correctly. Example: ``` 01416b1730218454c99b13592650cb170402b86742b4bab971565903b841829b SEQUENCE(2 elem) OBJECT IDENTIFIER1.3.6.1.4.1.311.2.1.12spcSpOpusInfo(Microsoft code signing) SET(1 elem) SEQUENCE(1 elem) [1](1 elem) [0]http://www.mozilla.com ``` ============================================================ Improve consistency of parsed serial numbers When parsing the issuer serial number, call mbedtls_x509_get_serial instead of parsing it as an integer directly with mbedtls_asn1_get_mpi. These two functions differ in how they treat serial numbers prepended with '00' to prevent them from being negative (the former preserves the '00', and the latter discards it). The embedded certs are parsed via a call to mbedtls_x509_crt_parse_der, which uses mbedtls_x509_get_serial behind the scenes, so there was an inconsistency between lief_obj.signature.signer_info.issuer[1] and lief_obj.signature.certificates[x].serial_number. Example: 8bf57d97dd917c4f823659266caaa33e7398406daf11ba8318e3f7414ee3fb24 ============================================================ Handle SpcLink and SpcString CHOICEs in SpcSpOpusInfo The Authenticode spec doc says that these can be CHOICES, so handle the easy ones and safely skip the others. ============================================================ Allow Authenticode sig to be parsed even if cert parsing fails By default, mbedtls doesn't support MD2 certs, which are fairly common in older signed executables. Ex: 1cb16f94cebdcad7dd05c8537375a6ff6379fcdb08528fc83889f26efaa84e2a ============================================================ Enable mbed TLS MD2 and MD4 support; add Unix debug options By default, mbedtls doesn't support MD2 certs, which are fairly common in older signed executables. Ex: 1cb16f94cebdcad7dd05c8537375a6ff6379fcdb08528fc83889f26efaa84e2a ============================================================ Set MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION flag Some older signed executables use certs with the SpcSpAgencyInfo Critical Extension, which mbed TLS doesn't support, so set MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION to have it skip this extension. Example: 781ca31416ec708a587851dafd90c661b86f244ab8b8475c4185e958e54ff838 ============================================================ Support accessing non-utf8 issuer names via Python For a few signatures where the issuer name contained non-utf8 characters, accessing the issuer name field in Python would raise a UnicodeDecodeError exception. Now this field is handled the same way the names in the individual certs are (I'm not sure if they get represented 100% correctly, but at least they are consistent, which is good enough for me). Example: 048f91b9302c88380fc66adac1e314d82733089ef3a31eadca5f0cb4169b195f
2019-07-26 17:51:14 -04:00
py::return_value_policy::copy)
2017-03-30 16:56:49 +02:00
.def_property_readonly("digest_algorithm",
&SignerInfo::digest_algorithm,
2021-01-05 19:26:10 +01:00
"Algorithm (" RST_CLASS_REF(lief.PE.ALGORITHMS) ") used to hash the file. "
"This value should match " RST_ATTR_REF_FULL(ContentInfo.digest_algorithm) " "
"and " RST_ATTR_REF_FULL(Signature.digest_algorithm) "")
2017-03-30 16:56:49 +02:00
2021-01-05 19:26:10 +01:00
.def_property_readonly("encryption_algorithm",
&SignerInfo::encryption_algorithm,
"Return algorithm (" RST_CLASS_REF(lief.PE.ALGORITHMS) ") used to encrypt the digest")
2017-03-30 16:56:49 +02:00
.def_property_readonly("encrypted_digest",
2021-01-05 19:26:10 +01:00
[] (const SignerInfo& info) {
const std::vector<uint8_t>& data = info.encrypted_digest();
return py::bytes(reinterpret_cast<const char*>(data.data()), data.size());
},
2017-03-30 16:56:49 +02:00
"Return the signature created by the signing certificate's private key")
.def_property_readonly("authenticated_attributes",
&SignerInfo::authenticated_attributes,
2021-01-05 19:26:10 +01:00
"Return an iterator over the authenticated attributes ("
"" RST_CLASS_REF(lief.PE.Attribute) ")",
py::return_value_policy::reference)
.def_property_readonly("unauthenticated_attributes",
&SignerInfo::unauthenticated_attributes,
"Return an iterator over the unauthenticated attributes ("
"" RST_CLASS_REF(lief.PE.Attribute) ")",
2017-03-30 16:56:49 +02:00
py::return_value_policy::reference)
2021-01-05 19:26:10 +01:00
.def("get_attribute",
&SignerInfo::get_attribute,
R"delim(
Return the authenticated or un-authenticated attribute matching the
given :class:`lief.PE.SIG_ATTRIBUTE_TYPES`
It returns **the first** entry that matches the given type. If it can't be
found, it returns None
)delim",
"type"_a,
py::return_value_policy::reference)
.def("get_auth_attribute",
&SignerInfo::get_auth_attribute,
R"delim(
Return the authenticated attribute matching the
given :class:`lief.PE.SIG_ATTRIBUTE_TYPES`
It returns **the first** entry that matches the given type. If it can't be
found, it returns None
)delim",
"type"_a,
py::return_value_policy::reference)
.def("get_unauth_attribute",
&SignerInfo::get_unauth_attribute,
R"delim(
Return the un-authenticated attribute matching the
given :class:`lief.PE.SIG_ATTRIBUTE_TYPES`
It returns **the first** entry that matches the given type. If it can't be
found, it returns a nullptr
)delim",
2021-01-05 19:26:10 +01:00
"type"_a,
py::return_value_policy::reference)
.def_property_readonly("cert",
static_cast<x509*(SignerInfo::*)()>(&SignerInfo::cert),
"" RST_CLASS_REF(lief.PE.x509) " certificate used by this signer. If it can't be found, it returns None",
py::return_value_policy::reference)
.def("__hash__",
[] (const SignerInfo& obj) {
return Hash::hash(obj);
})
2017-03-30 16:56:49 +02:00
.def("__str__",
[] (const SignerInfo& signer_info)
{
std::ostringstream stream;
stream << signer_info;
std::string str = stream.str();
return str;
});
}
2018-06-08 14:58:00 +02:00
}
}