/* * Copyright (C) 2021-2023 Michał Trojnara * Author: Małgorzata Olszówka */ #define OPENSSL_API_COMPAT 0x10100000L #define OPENSSL_NO_DEPRECATED #if defined(_MSC_VER) || defined(__MINGW32__) #define HAVE_WINDOWS_H #endif /* _MSC_VER || __MINGW32__ */ #ifdef HAVE_WINDOWS_H #define NOCRYPT #define WIN32_LEAN_AND_MEAN #include #endif /* HAVE_WINDOWS_H */ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #include #ifndef _WIN32 #include #ifdef HAVE_SYS_MMAN_H #include #endif /* HAVE_SYS_MMAN_H */ #ifdef HAVE_TERMIOS_H #include #endif /* HAVE_TERMIOS_H */ #endif /* _WIN32 */ #include #include #include #include #include #include #include #include #ifndef OPENSSL_NO_ENGINE #include #endif /* OPENSSL_NO_ENGINE */ #include #include #include #include #include #include #if OPENSSL_VERSION_NUMBER>=0x30000000L #include #endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */ #include #include #include /* X509_PURPOSE */ #ifdef ENABLE_CURL #ifdef __CYGWIN__ #ifndef SOCKET #define SOCKET UINT_PTR #endif /* SOCKET */ #endif /* __CYGWIN__ */ #include #define MAX_TS_SERVERS 256 #endif /* ENABLE_CURL */ #if defined (HAVE_TERMIOS_H) || defined (HAVE_GETPASS) #define PROVIDE_ASKPASS 1 #endif #ifdef _WIN32 #define FILE_CREATE_MODE "w+b" #else #define FILE_CREATE_MODE "w+bx" #endif #define GET_UINT8_LE(p) ((const u_char *)(p))[0] #define GET_UINT16_LE(p) (uint16_t)(((const u_char *)(p))[0] | \ (((const u_char *)(p))[1] << 8)) #define GET_UINT32_LE(p) (uint32_t)(((const u_char *)(p))[0] | \ (((const u_char *)(p))[1] << 8) | \ (((const u_char *)(p))[2] << 16) | \ (((const u_char *)(p))[3] << 24)) #define PUT_UINT8_LE(i, p) ((u_char *)(p))[0] = (u_char)((i) & 0xff); #define PUT_UINT16_LE(i,p) ((u_char *)(p))[0] = (u_char)((i) & 0xff); \ ((u_char *)(p))[1] = (u_char)(((i) >> 8) & 0xff) #define PUT_UINT32_LE(i,p) ((u_char *)(p))[0] = (u_char)((i) & 0xff); \ ((u_char *)(p))[1] = (u_char)(((i) >> 8) & 0xff); \ ((u_char *)(p))[2] = (u_char)(((i) >> 16) & 0xff); \ ((u_char *)(p))[3] = (u_char)(((i) >> 24) & 0xff) #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif #define SIZE_64K 65536 /* 2^16 */ #define SIZE_16M 16777216 /* 2^24 */ /* * Macro names: * linux: __BYTE_ORDER == __LITTLE_ENDIAN | __BIG_ENDIAN * BYTE_ORDER == LITTLE_ENDIAN | BIG_ENDIAN * bsd: _BYTE_ORDER == _LITTLE_ENDIAN | _BIG_ENDIAN * BYTE_ORDER == LITTLE_ENDIAN | BIG_ENDIAN * solaris: _LITTLE_ENDIAN | _BIG_ENDIAN */ #ifndef BYTE_ORDER #define LITTLE_ENDIAN 1234 #define BIG_ENDIAN 4321 #define BYTE_ORDER LITTLE_ENDIAN #endif /* BYTE_ORDER */ #if !defined(BYTE_ORDER) || !defined(LITTLE_ENDIAN) || !defined(BIG_ENDIAN) #error "Cannot determine the endian-ness of this platform" #endif #ifndef LOWORD #define LOWORD(x) ((x) & 0xFFFF) #endif /* LOWORD */ #ifndef HIWORD #define HIWORD(x) (((x) >> 16) & 0xFFFF) #endif /* HIWORD */ #if BYTE_ORDER == BIG_ENDIAN #define LE_UINT16(x) ((((x) >> 8) & 0x00FF) | \ (((x) << 8) & 0xFF00)) #define LE_UINT32(x) (((x) >> 24) | \ (((x) & 0x00FF0000) >> 8) | \ (((x) & 0x0000FF00) << 8) | \ ((x) << 24)) #else #define LE_UINT16(x) (x) #define LE_UINT32(x) (x) #endif /* BYTE_ORDER == BIG_ENDIAN */ #define MIN(a,b) ((a) < (b) ? a : b) #define INVALID_TIME ((time_t)-1) /* Microsoft OID Authenticode */ #define SPC_INDIRECT_DATA_OBJID "1.3.6.1.4.1.311.2.1.4" #define SPC_STATEMENT_TYPE_OBJID "1.3.6.1.4.1.311.2.1.11" #define SPC_SP_OPUS_INFO_OBJID "1.3.6.1.4.1.311.2.1.12" #define SPC_PE_IMAGE_DATA_OBJID "1.3.6.1.4.1.311.2.1.15" #define SPC_CAB_DATA_OBJID "1.3.6.1.4.1.311.2.1.25" #define SPC_SIPINFO_OBJID "1.3.6.1.4.1.311.2.1.30" #define SPC_PE_IMAGE_PAGE_HASHES_V1 "1.3.6.1.4.1.311.2.3.1" /* SHA1 */ #define SPC_PE_IMAGE_PAGE_HASHES_V2 "1.3.6.1.4.1.311.2.3.2" /* SHA256 */ #define SPC_NESTED_SIGNATURE_OBJID "1.3.6.1.4.1.311.2.4.1" /* Microsoft OID Time Stamping */ #define SPC_TIME_STAMP_REQUEST_OBJID "1.3.6.1.4.1.311.3.2.1" #define SPC_RFC3161_OBJID "1.3.6.1.4.1.311.3.3.1" /* Microsoft OID Crypto 2.0 */ #define MS_CTL_OBJID "1.3.6.1.4.1.311.10.1" /* Microsoft OID Microsoft_Java */ #define MS_JAVA_SOMETHING "1.3.6.1.4.1.311.15.1" #define SPC_UNAUTHENTICATED_DATA_BLOB_OBJID "1.3.6.1.4.1.42921.1.2.1" /* Public Key Cryptography Standards PKCS#9 */ #define PKCS9_MESSAGE_DIGEST "1.2.840.113549.1.9.4" #define PKCS9_SIGNING_TIME "1.2.840.113549.1.9.5" #define PKCS9_COUNTER_SIGNATURE "1.2.840.113549.1.9.6" /* WIN_CERTIFICATE structure declared in Wintrust.h */ #define WIN_CERT_REVISION_2_0 0x0200 #define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002 /* * FLAG_PREV_CABINET is set if the cabinet file is not the first in a set * of cabinet files. When this bit is set, the szCabinetPrev and szDiskPrev * fields are present in this CFHEADER. */ #define FLAG_PREV_CABINET 0x0001 /* * FLAG_NEXT_CABINET is set if the cabinet file is not the last in a set of * cabinet files. When this bit is set, the szCabinetNext and szDiskNext * fields are present in this CFHEADER. */ #define FLAG_NEXT_CABINET 0x0002 /* * FLAG_RESERVE_PRESENT is set if the cabinet file contains any reserved * fields. When this bit is set, the cbCFHeader, cbCFFolder, and cbCFData * fields are present in this CFHEADER. */ #define FLAG_RESERVE_PRESENT 0x0004 #define DO_EXIT_0(x) { printf(x); goto err_cleanup; } #define DO_EXIT_1(x, y) { printf(x, y); goto err_cleanup; } #define DO_EXIT_2(x, y, z) { printf(x, y, z); goto err_cleanup; } typedef enum { CMD_SIGN, CMD_EXTRACT, CMD_REMOVE, CMD_VERIFY, CMD_ADD, CMD_ATTACH, CMD_HELP, CMD_DEFAULT } cmd_type_t; typedef unsigned char u_char; typedef struct { char *infile; char *outfile; char *sigfile; char *certfile; char *xcertfile; char *keyfile; char *pvkfile; char *pkcs12file; int output_pkcs7; #ifndef OPENSSL_NO_ENGINE char *p11engine; char *p11module; char *p11cert; #endif /* OPENSSL_NO_ENGINE */ int askpass; char *readpass; char *pass; int comm; int pagehash; char *desc; const EVP_MD *md; char *url; time_t time; #ifdef ENABLE_CURL char *turl[MAX_TS_SERVERS]; int nturl; char *tsurl[MAX_TS_SERVERS]; int ntsurl; char *proxy; int noverifypeer; #endif /* ENABLE_CURL */ int addBlob; int nest; int ignore_timestamp; int verbose; int add_msi_dse; char *catalog; char *cafile; char *crlfile; char *tsa_cafile; char *tsa_crlfile; char *leafhash; int jp; #if OPENSSL_VERSION_NUMBER>=0x30000000L int legacy; #endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */ EVP_PKEY *pkey; X509 *cert; STACK_OF(X509) *certs; STACK_OF(X509) *xcerts; STACK_OF(X509_CRL) *crls; cmd_type_t cmd; char *indata; } GLOBAL_OPTIONS; /* * ASN.1 definitions (more or less from official MS Authenticode docs) */ typedef struct { int type; union { ASN1_BMPSTRING *unicode; ASN1_IA5STRING *ascii; } value; } SpcString; DECLARE_ASN1_FUNCTIONS(SpcString) typedef struct { ASN1_OCTET_STRING *classId; ASN1_OCTET_STRING *serializedData; } SpcSerializedObject; DECLARE_ASN1_FUNCTIONS(SpcSerializedObject) typedef struct { int type; union { ASN1_IA5STRING *url; SpcSerializedObject *moniker; SpcString *file; } value; } SpcLink; DECLARE_ASN1_FUNCTIONS(SpcLink) typedef struct { SpcString *programName; SpcLink *moreInfo; } SpcSpOpusInfo; DECLARE_ASN1_FUNCTIONS(SpcSpOpusInfo) typedef struct { ASN1_OBJECT *type; ASN1_TYPE *value; } SpcAttributeTypeAndOptionalValue; DECLARE_ASN1_FUNCTIONS(SpcAttributeTypeAndOptionalValue) typedef struct { ASN1_OBJECT *algorithm; ASN1_TYPE *parameters; } AlgorithmIdentifier; DECLARE_ASN1_FUNCTIONS(AlgorithmIdentifier) typedef struct { AlgorithmIdentifier *digestAlgorithm; ASN1_OCTET_STRING *digest; } DigestInfo; DECLARE_ASN1_FUNCTIONS(DigestInfo) typedef struct { SpcAttributeTypeAndOptionalValue *data; DigestInfo *messageDigest; } SpcIndirectDataContent; DECLARE_ASN1_FUNCTIONS(SpcIndirectDataContent) typedef struct CatalogAuthAttr_st { ASN1_OBJECT *type; ASN1_TYPE *contents; } CatalogAuthAttr; DEFINE_STACK_OF(CatalogAuthAttr) DECLARE_ASN1_FUNCTIONS(CatalogAuthAttr) typedef struct { AlgorithmIdentifier *digestAlgorithm; ASN1_OCTET_STRING *digest; } MessageImprint; DECLARE_ASN1_FUNCTIONS(MessageImprint) #ifdef ENABLE_CURL typedef struct { ASN1_OBJECT *type; ASN1_OCTET_STRING *signature; } TimeStampRequestBlob; DECLARE_ASN1_FUNCTIONS(TimeStampRequestBlob) typedef struct { ASN1_OBJECT *type; TimeStampRequestBlob *blob; } TimeStampRequest; DECLARE_ASN1_FUNCTIONS(TimeStampRequest) /* RFC3161 Time stamping */ typedef struct { ASN1_INTEGER *status; STACK_OF(ASN1_UTF8STRING) *statusString; ASN1_BIT_STRING *failInfo; } PKIStatusInfo; DECLARE_ASN1_FUNCTIONS(PKIStatusInfo) typedef struct { PKIStatusInfo *status; PKCS7 *token; } TimeStampResp; DECLARE_ASN1_FUNCTIONS(TimeStampResp) typedef struct { ASN1_INTEGER *version; MessageImprint *messageImprint; ASN1_OBJECT *reqPolicy; ASN1_INTEGER *nonce; ASN1_BOOLEAN certReq; STACK_OF(X509_EXTENSION) *extensions; } TimeStampReq; DECLARE_ASN1_FUNCTIONS(TimeStampReq) #endif /* ENABLE_CURL */ typedef struct { ASN1_INTEGER *seconds; ASN1_INTEGER *millis; ASN1_INTEGER *micros; } TimeStampAccuracy; DECLARE_ASN1_FUNCTIONS(TimeStampAccuracy) typedef struct { ASN1_INTEGER *version; ASN1_OBJECT *policy_id; MessageImprint *messageImprint; ASN1_INTEGER *serial; ASN1_GENERALIZEDTIME *time; TimeStampAccuracy *accuracy; ASN1_BOOLEAN ordering; ASN1_INTEGER *nonce; GENERAL_NAME *tsa; STACK_OF(X509_EXTENSION) *extensions; } TimeStampToken; DECLARE_ASN1_FUNCTIONS(TimeStampToken) typedef struct { ASN1_OCTET_STRING *digest; STACK_OF(CatalogAuthAttr) *attributes; } CatalogInfo; DEFINE_STACK_OF(CatalogInfo) DECLARE_ASN1_FUNCTIONS(CatalogInfo) typedef struct { /* 1.3.6.1.4.1.311.12.1.1 MS_CATALOG_LIST */ SpcAttributeTypeAndOptionalValue *type; ASN1_OCTET_STRING *identifier; ASN1_UTCTIME *time; /* 1.3.6.1.4.1.311.12.1.2 CatalogVersion = 1 * 1.3.6.1.4.1.311.12.1.3 CatalogVersion = 2 */ SpcAttributeTypeAndOptionalValue *version; STACK_OF(CatalogInfo) *header_attributes; /* 1.3.6.1.4.1.311.12.2.1 CAT_NAMEVALUE_OBJID */ ASN1_TYPE *filename; } MsCtlContent; DECLARE_ASN1_FUNCTIONS(MsCtlContent) typedef struct file_format_st FILE_FORMAT; typedef struct msi_ctx_st MSI_CTX; typedef struct pe_ctx_st PE_CTX; typedef struct cab_ctx_st CAB_CTX; typedef struct cat_ctx_st CAT_CTX; typedef struct { FILE_FORMAT *format; GLOBAL_OPTIONS *options; union { MSI_CTX *msi_ctx; PE_CTX *pe_ctx; CAB_CTX *cab_ctx; CAT_CTX *cat_ctx; }; } FILE_FORMAT_CTX; extern FILE_FORMAT file_format_msi; extern FILE_FORMAT file_format_pe; extern FILE_FORMAT file_format_cab; extern FILE_FORMAT file_format_cat; struct file_format_st { FILE_FORMAT_CTX *(*ctx_new) (GLOBAL_OPTIONS *option, BIO *hash, BIO *outdata); ASN1_OBJECT *(*data_blob_get) (u_char **p, int *plen, FILE_FORMAT_CTX *ctx); int (*check_file) (FILE_FORMAT_CTX *ctx, int detached); u_char *(*digest_calc) (FILE_FORMAT_CTX *ctx, const EVP_MD *md); int (*verify_digests) (FILE_FORMAT_CTX *ctx, PKCS7 *p7); int (*verify_indirect_data) (FILE_FORMAT_CTX *ctx, SpcAttributeTypeAndOptionalValue *obj); PKCS7 *(*pkcs7_extract) (FILE_FORMAT_CTX *ctx); int (*remove_pkcs7) (FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata); PKCS7 *(*pkcs7_prepare) (FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata); int (*append_pkcs7) (FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7); void (*update_data_size) (FILE_FORMAT_CTX *data, BIO *outdata, PKCS7 *p7); BIO *(*bio_free) (BIO *hash, BIO *outdata); void (*ctx_cleanup) (FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata); }; /* Local Variables: c-basic-offset: 4 tab-width: 4 indent-tabs-mode: t End: vim: set ts=4 noexpandtab: */