osslsigncode 0.1.1

In-process Rust bindings for the vendored osslsigncode Authenticode implementation
//! FFI that bindgen cannot (or should not) emit: promoted `osslsigncode.c`
//! locals and a few libcrypto entry points missing from `openssl-sys`.

use std::os::raw::{c_char, c_int, c_void};

use openssl_sys::{BIO, EVP_MD, PKCS7};

// Re-exported so `crate::ffi` stays the single FFI facade even for symbols that
// happen to live in `openssl-sys`.
pub use openssl_sys::{BIO_ctrl, PKCS7_free};

use crate::bindings::{FILE_FORMAT_CTX, GLOBAL_OPTIONS};

/// Opaque OpenSSL UI method (not currently in `openssl-sys`).
#[repr(C)]
pub struct UI_METHOD {
    _private: [u8; 0],
}

// Promoted locals from vendored `osslsigncode.c`.
unsafe extern "C" {
    pub fn free_options(options: *mut GLOBAL_OPTIONS);
    pub fn read_password(options: *mut GLOBAL_OPTIONS) -> c_int;
    pub fn read_crypto_params(options: *mut GLOBAL_OPTIONS) -> c_int;
    pub fn verify_signed_file(
        ctx: *mut FILE_FORMAT_CTX,
        options: *mut GLOBAL_OPTIONS,
        print: c_int,
    ) -> c_int;
    pub fn add_timestamp_and_blob(p7: *mut PKCS7, ctx: *mut FILE_FORMAT_CTX) -> c_int;
    pub fn add_nested_timestamp_and_blob(
        p7: *mut PKCS7,
        ctx: *mut FILE_FORMAT_CTX,
        index: c_int,
    ) -> c_int;
    pub fn cursig_set_nested(cursig: *mut PKCS7, p7: *mut PKCS7) -> c_int;
    pub fn nested_signatures_number_get(p7: *mut PKCS7) -> c_int;
    pub fn pkcs7_get_sigfile(ctx: *mut FILE_FORMAT_CTX) -> *mut PKCS7;
    pub fn check_attached_data(options: *mut GLOBAL_OPTIONS) -> c_int;
    pub fn ui_osslsigncode() -> *mut UI_METHOD;
    pub fn bio_new_file(filename: *const c_char, mode: *const c_char) -> *mut BIO;
    pub static mut ui_method: *mut UI_METHOD;
}

#[cfg(ossl_has_providers_cleanup)]
unsafe extern "C" {
    pub fn providers_cleanup();
}

#[cfg(not(ossl_has_providers_cleanup))]
pub unsafe fn providers_cleanup() {}

#[cfg(ossl_has_engine_ctrl)]
unsafe extern "C" {
    pub fn engine_control_set(options: *mut GLOBAL_OPTIONS, arg: *const c_char);
}

#[cfg(not(ossl_has_engine_ctrl))]
pub unsafe fn engine_control_set(_options: *mut GLOBAL_OPTIONS, _arg: *const c_char) {}

// Genuinely missing from `openssl-sys` at this version.
unsafe extern "C" {
    pub fn BIO_f_md() -> *const openssl_sys::BIO_METHOD;
    pub fn BIO_free(a: *mut BIO) -> c_int;
    pub fn BIO_pop(b: *mut BIO) -> *mut BIO;
    pub fn UI_destroy_method(ui: *mut UI_METHOD);
}

/// `BIO_set_md` is a C macro around `BIO_ctrl` in OpenSSL.
///
/// # Safety
///
/// `b` must be a valid message-digest `BIO` and `md` a valid `EVP_MD` (or null),
/// both living for the duration of the call.
#[allow(non_snake_case)]
pub unsafe fn BIO_set_md(b: *mut BIO, md: *const EVP_MD) -> c_int {
    const BIO_C_SET_MD: c_int = 111;
    unsafe { BIO_ctrl(b, BIO_C_SET_MD, 0, md as *mut c_void) as c_int }
}