uthenticode 2.0.1-fa0cba9
Loading...
Searching...
No Matches
uthenticode.h
Go to the documentation of this file.
1#pragma once
2
3#include <openssl/asn1.h>
4#include <openssl/asn1t.h>
5#include <openssl/crypto.h>
6#include <openssl/x509.h>
7#include <pe-parse/parse.h>
8
9#include <cstdint>
10#include <exception>
11#include <memory>
12#include <optional>
13#include <vector>
14
20namespace uthenticode {
21
25namespace impl {
26typedef struct {
27 ASN1_OBJECT *type;
28 ASN1_TYPE *value;
30
31typedef struct {
32 X509_ALGOR *digestAlgorithm;
33 ASN1_OCTET_STRING *digest;
35
40
41/* Custom ASN.1 insanity is quarantined to the impl namespace.
42 */
44DECLARE_ASN1_FUNCTIONS(Authenticode_DigestInfo)
45DECLARE_ASN1_FUNCTIONS(Authenticode_SpcIndirectDataContent)
46
47/* OpenSSL defines OPENSSL_free as a macro, which we can't use with decltype.
48 * So we wrap it here for use with unique_ptr.
49 */
50void OpenSSL_free(void *ptr);
51
52/* Since OpenSSL 3.0.0 SK_X509_free is defined as a macro, which we can't use with decltype.
53 * So we wrap it here for use with unique_ptr.
54 */
55void SK_X509_free(stack_st_X509 *ptr);
56
57/* Convenient self-releasing aliases for libcrypto and custom ASN.1 types.
58 */
59using BIO_ptr = std::unique_ptr<BIO, decltype(&BIO_free)>;
60using ASN1_OBJECT_ptr = std::unique_ptr<ASN1_OBJECT, decltype(&ASN1_OBJECT_free)>;
61using ASN1_TYPE_ptr = std::unique_ptr<ASN1_TYPE, decltype(&ASN1_TYPE_free)>;
62using OpenSSL_ptr = std::unique_ptr<char, decltype(&OpenSSL_free)>;
63using BN_ptr = std::unique_ptr<BIGNUM, decltype(&BN_free)>;
64using STACK_OF_X509_ptr = std::unique_ptr<STACK_OF(X509), decltype(&SK_X509_free)>;
65
66using SectionList = std::vector<const peparse::bounded_buffer *>;
67
68constexpr auto SPC_INDIRECT_DATA_OID = "1.3.6.1.4.1.311.2.1.4";
69constexpr auto SPC_NESTED_SIGNATURE_OID = "1.3.6.1.4.1.311.2.4.1";
70} // namespace impl
71
80enum class certificate_revision : std::uint16_t {
81 CERT_REVISION_1_0 = 0x0100,
82 CERT_REVISION_2_0 = 0x0200,
83};
84
91enum class certificate_type : std::uint16_t {
92 CERT_TYPE_X509 = 0x0001,
94 CERT_TYPE_RESERVED_1 = 0x0003,
95 CERT_TYPE_PKCS1_SIGN = 0x0009,
96};
97
101enum class checksum_kind : std::uint8_t {
102 UNKNOWN,
103 MD5,
104 SHA1,
105 SHA256,
106};
107
108std::ostream &operator<<(std::ostream &os, checksum_kind kind);
109
114using Checksum = std::tuple<checksum_kind, std::string>;
115
119struct FormatError : public std::runtime_error {
120 public:
121 FormatError(const char *msg) : std::runtime_error(msg) {
122 }
123};
124
132 public:
133 friend class SignedData;
134
138 const std::string &get_subject() const {
139 return subject_;
140 }
141
145 const std::string &get_issuer() const {
146 return issuer_;
147 }
148
152 const std::string &get_serial_number() const {
153 return serial_number_;
154 }
155
156 /* TODO: Maybe add data_ and get_data(), with data_ populated from i2d_X509.
157 */
158
159#ifndef UTHENTICODE_DEFAULT_XN_FLAGS
160 static constexpr unsigned long const default_xn_flags =
161 XN_FLAG_RFC2253 | ASN1_STRFLGS_UTF8_CONVERT;
162#else
163 static constexpr unsigned long const default_xn_flags = (UTHENTICODE_DEFAULT_XN_FLAGS);
164#endif
165 static_assert((default_xn_flags & XN_FLAG_COMPAT) == 0,
166 "Logic is incompatible with XN_FLAG_COMPAT");
167
168 private:
169 explicit Certificate(X509 *cert);
170 std::string subject_;
171 std::string issuer_;
172 std::string serial_number_;
173};
174
179 public:
185 SignedData(std::vector<std::uint8_t> cert_buf);
186 SignedData(SignedData &&s) noexcept;
187 SignedData(const SignedData &) = delete;
188 ~SignedData();
189
195 bool verify_signature() const;
196
202 Checksum get_checksum() const;
203
209 std::vector<Certificate> get_signers() const;
210
216 std::vector<Certificate> get_certificates() const;
217
222 std::optional<SignedData> get_nested_signed_data() const;
223
227 std::vector<std::uint8_t> const &get_raw_data() const;
228
229 private:
230 impl::Authenticode_SpcIndirectDataContent *get_indirect_data() const;
231
232 std::vector<std::uint8_t> cert_buf_;
233 PKCS7 *p7_{nullptr};
234 impl::Authenticode_SpcIndirectDataContent *indirect_data_{nullptr};
235};
236
245class WinCert {
246 public:
247 WinCert(certificate_revision revision, certificate_type type, std::vector<std::uint8_t> cert_buf)
248 : revision_(revision), type_(type), cert_buf_(cert_buf) {
249 }
250
254 std::size_t get_length() const {
255 return cert_buf_.size();
256 }
257
262 return revision_;
263 }
264
269 return type_;
270 }
271
276 std::optional<SignedData> as_signed_data() const;
277
278 private:
279 certificate_revision revision_;
280 certificate_type type_;
281 std::vector<std::uint8_t> cert_buf_;
282};
283
290std::vector<WinCert> read_certs(peparse::parsed_pe *pe);
291
298std::vector<Checksum> get_checksums(peparse::parsed_pe *pe);
299
310std::optional<std::string> calculate_checksum(peparse::parsed_pe *pe, checksum_kind kind);
311
324bool verify(peparse::parsed_pe *pe);
325
326} // namespace uthenticode
Definition uthenticode.h:131
const std::string & get_subject() const
Definition uthenticode.h:138
const std::string & get_issuer() const
Definition uthenticode.h:145
const std::string & get_serial_number() const
Definition uthenticode.h:152
Definition uthenticode.h:178
SignedData(const SignedData &)=delete
Definition uthenticode.h:245
certificate_revision get_revision() const
Definition uthenticode.h:261
std::size_t get_length() const
Definition uthenticode.h:254
WinCert(certificate_revision revision, certificate_type type, std::vector< std::uint8_t > cert_buf)
Definition uthenticode.h:247
certificate_type get_type() const
Definition uthenticode.h:268
std::unique_ptr< ASN1_TYPE, decltype(&ASN1_TYPE_free)> ASN1_TYPE_ptr
Definition uthenticode.h:61
std::unique_ptr< char, decltype(&OpenSSL_free)> OpenSSL_ptr
Definition uthenticode.h:62
void SK_X509_free(stack_st_X509 *ptr)
void OpenSSL_free(void *ptr)
std::unique_ptr< ASN1_OBJECT, decltype(&ASN1_OBJECT_free)> ASN1_OBJECT_ptr
Definition uthenticode.h:60
std::vector< const peparse::bounded_buffer * > SectionList
Definition uthenticode.h:66
std::unique_ptr< BIGNUM, decltype(&BN_free)> BN_ptr
Definition uthenticode.h:63
std::unique_ptr< BIO, decltype(&BIO_free)> BIO_ptr
Definition uthenticode.h:59
constexpr auto SPC_NESTED_SIGNATURE_OID
Definition uthenticode.h:69
std::unique_ptr< STACK_OF(X509), decltype(&SK_X509_free)> STACK_OF_X509_ptr
Definition uthenticode.h:64
constexpr auto SPC_INDIRECT_DATA_OID
Definition uthenticode.h:68
Definition uthenticode.h:20
certificate_revision
Definition uthenticode.h:80
std::optional< std::string > calculate_checksum(peparse::parsed_pe *pe, checksum_kind kind)
Definition uthenticode.cpp:498
certificate_type
Definition uthenticode.h:91
std::ostream & operator<<(std::ostream &os, checksum_kind kind)
Definition uthenticode.cpp:130
bool verify(peparse::parsed_pe *pe)
Definition uthenticode.cpp:648
checksum_kind
Definition uthenticode.h:101
std::tuple< checksum_kind, std::string > Checksum
Definition uthenticode.h:114
std::vector< WinCert > read_certs(peparse::parsed_pe *pe)
Definition uthenticode.cpp:432
std::vector< Checksum > get_checksums(peparse::parsed_pe *pe)
Definition uthenticode.cpp:479
Definition uthenticode.h:119
FormatError(const char *msg)
Definition uthenticode.h:121
X509_ALGOR * digestAlgorithm
Definition uthenticode.h:32
ASN1_OCTET_STRING * digest
Definition uthenticode.h:33
Authenticode_DigestInfo * messageDigest
Definition uthenticode.h:38
Authenticode_SpcAttributeTypeAndOptionalValue * data
Definition uthenticode.h:37