/* Copyright 2017 - 2022 R. Thomas * Copyright 2017 - 2022 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. */ #ifndef LIEF_PE_X509_H_ #define LIEF_PE_X509_H_ #include #include #include "LIEF/Object.hpp" #include "LIEF/visibility.h" #include "LIEF/PE/enums.hpp" #include "LIEF/PE/signature/types.hpp" #include "LIEF/enums.hpp" struct mbedtls_x509_crt; namespace LIEF { namespace PE { class Parser; class SignatureParser; class Signature; class RsaInfo; //! Interface over a x509 certificate class LIEF_API x509 : public Object { friend class Parser; friend class SignatureParser; friend class Signature; public: //! Tuple (Year, Month, Day, Hour, Minute, Second) using date_t = std::array; using certificates_t = std::vector; //! Parse x509 certificate(s) from file path static certificates_t parse(const std::string& path); //! Parse x509 certificate(s) from raw blob static certificates_t parse(const std::vector& content); //! Return True if ``before`` is *before* than ``after``. False otherwise static bool check_time(const date_t& before, const date_t& after); //! True if the given time is in the **past** according to the clock's system static bool time_is_past(const date_t& to); //! True if the given time is in the future according to the clock's system static bool time_is_future(const date_t& from); //! Public key scheme enum class KEY_TYPES { NONE = 0, ///< Unknown scheme RSA, ///< RSA Scheme ECKEY, ///< Elliptic-curve scheme ECKEY_DH, ///< Elliptic-curve Diffie-Hellman ECDSA, ///< Elliptic-curve Digital Signature Algorithm RSA_ALT, ///< RSA scheme with an alternative implementation for signing and decrypting RSASSA_PSS, ///< RSA Probabilistic signature scheme }; //! Mirror of mbedtls's X509 Verify codes: MBEDTLS_X509_XX //! //! It must be sync with include/mbedtls/x509.h enum class VERIFICATION_FLAGS { OK = 0, /**< The verification succeed */ BADCERT_EXPIRED = 1 << 0, /**< The certificate validity has expired. */ BADCERT_REVOKED = 1 << 1, /**< The certificate has been revoked (is on a CRL). */ BADCERT_CN_MISMATCH = 1 << 2, /**< The certificate Common Name (CN) does not match with the expected CN. */ BADCERT_NOT_TRUSTED = 1 << 3, /**< The certificate is not correctly signed by the trusted CA. */ BADCRL_NOT_TRUSTED = 1 << 4, /**< The CRL is not correctly signed by the trusted CA. */ BADCRL_EXPIRED = 1 << 5, /**< The CRL is expired. */ BADCERT_MISSING = 1 << 6, /**< Certificate was missing. */ BADCERT_SKIP_VERIFY = 1 << 7, /**< Certificate verification was skipped. */ BADCERT_OTHER = 1 << 8, /**< Other reason (can be used by verify callback) */ BADCERT_FUTURE = 1 << 9, /**< The certificate validity starts in the future. */ BADCRL_FUTURE = 1 << 10, /**< The CRL is from the future */ BADCERT_KEY_USAGE = 1 << 11, /**< Usage does not match the keyUsage extension. */ BADCERT_EXT_KEY_USAGE = 1 << 12, /**< Usage does not match the extendedKeyUsage extension. */ BADCERT_NS_CERT_TYPE = 1 << 13, /**< Usage does not match the nsCertType extension. */ BADCERT_BAD_MD = 1 << 14, /**< The certificate is signed with an unacceptable hash. */ BADCERT_BAD_PK = 1 << 15, /**< The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ BADCERT_BAD_KEY = 1 << 16, /**< The certificate is signed with an unacceptable key (eg bad curve, RSA too short). */ BADCRL_BAD_MD = 1 << 17, /**< The CRL is signed with an unacceptable hash. */ BADCRL_BAD_PK = 1 << 18, /**< The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ BADCRL_BAD_KEY = 1 << 19, /**< The CRL is signed with an unacceptable key (eg bad curve, RSA too short). */ }; //! Key usage as defined in [RFC #5280 - section-4.2.1.3](https://tools.ietf.org/html/rfc5280#section-4.2.1.3) enum class KEY_USAGE { DIGITAL_SIGNATURE = 0, /**< The key is used for digital signature */ NON_REPUDIATION, /**< The key is used for digital signature AND to protects against falsely denying some action */ KEY_ENCIPHERMENT, /**< The key is used for enciphering private or secret keys */ DATA_ENCIPHERMENT, /**< The key is used for directly enciphering raw user data without the use of an intermediate symmetric cipher */ KEY_AGREEMENT, /**< The Key is used for key agreement. (e.g. with Diffie-Hellman) */ KEY_CERT_SIGN, /**< The key is used for verifying signatures on public key certificates */ CRL_SIGN, /**< The key is used for verifying signatures on certificate revocation lists */ ENCIPHER_ONLY, /**< In **association with** KEY_AGREEMENT (otherwise the meaning is undefined), the key is only used for enciphering data while performing key agreement */ DECIPHER_ONLY, /**< In **association with** KEY_AGREEMENT (otherwise the meaning is undefined), the key is only used for deciphering data while performing key agreement */ }; x509(mbedtls_x509_crt* ca); x509(const x509& other); x509& operator=(x509 other); void swap(x509& other); //! X.509 version. (1=v1, 2=v2, 3=v3) uint32_t version() const; //! Unique id for certificate issued by a specific CA. std::vector serial_number() const; //! Signature algorithm (OID) oid_t signature_algorithm() const; //! Start time of certificate validity date_t valid_from() const; //! End time of certificate validity date_t valid_to() const; //! Issuer informations std::string issuer() const; //! Subject informations std::string subject() const; //! Try to decrypt the given signature and check if it matches the given hash according to //! the hash algorithm provided bool check_signature(const std::vector& hash, const std::vector& signature, ALGORITHMS digest) const; //! The raw x509 bytes (DER encoded) std::vector raw() const; //! Return the underlying public-key scheme KEY_TYPES key_type() const; //! **If** the underlying public-key scheme is RSA, return the RSA information. //! Otherwise, return a nullptr std::unique_ptr rsa_info() const; //! Verify that this certificate has been used **to trust** the given certificate VERIFICATION_FLAGS verify(const x509& ca) const; //! Verify that this certificate **is trusted** by the given CA list VERIFICATION_FLAGS is_trusted_by(const std::vector& ca) const; //! Policy information terms as OID (see RFC #5280) std::vector certificate_policies() const; //! Purpose of the key contained in the certificate std::vector key_usage() const; //! Indicates one or more purposes for which the certified public key may be used (OID types) std::vector ext_key_usage() const; bool is_ca() const; //! The signature of the certificate std::vector signature() const; void accept(Visitor& visitor) const override; virtual ~x509(); LIEF_API friend std::ostream& operator<<(std::ostream& os, const x509& x509_cert); private: x509(); mbedtls_x509_crt* x509_cert_ = nullptr; }; } } ENABLE_BITMASK_OPERATORS(LIEF::PE::x509::VERIFICATION_FLAGS) #endif