codesigned/winapi/
mod.rs

1mod constants;
2mod oids;
3
4extern crate widestring;
5
6use std::mem::{ size_of };
7use std::ptr::{null, null_mut};
8use std::slice::from_raw_parts_mut;
9use std::string::ToString;
10use widestring::WideCString;
11
12pub use self::constants::*;
13pub use self::oids::*;
14
15#[repr(C)]
16#[derive(Debug, Clone)]
17pub struct CryptoAttribute {
18    pub obj_id: *const u8,
19    pub c_value: u32,
20    pub rg_value: *const CryptoApiBlob,
21}
22
23impl Default for CryptoAttribute {
24    fn default() -> CryptoAttribute {
25        CryptoAttribute {
26            obj_id: null(),
27            c_value: 0,
28            rg_value: null(),
29        }
30    }
31}
32
33#[repr(C)]
34#[derive(Debug)]
35pub struct CryptoAttributes {
36    pub c_attr: u32,
37    pub rg_attr: *const CryptoAttribute,
38}
39
40#[repr(C)]
41#[derive(Debug)]
42pub struct CryptoAlgorithmIdentifier {
43    pub obj_id: *const u8,
44    pub parameters: CryptoApiBlob,
45}
46
47impl Default for CryptoAlgorithmIdentifier {
48    fn default() -> CryptoAlgorithmIdentifier {
49        CryptoAlgorithmIdentifier {
50            obj_id: null(),
51            parameters: Default::default(),
52        }
53    }
54}
55
56#[repr(C)]
57#[derive(Clone, Debug)]
58pub struct CryptoApiBlob {
59    pub len: u32,
60    pub data: *mut u8,
61}
62
63impl CryptoApiBlob {
64    pub fn from(&mut self, blob: &CryptoApiBlob) {
65        self.len = blob.len;
66        self.data = blob.data;
67    }
68}
69
70impl ToString for CryptoApiBlob {
71    fn to_string(&self) -> String {
72        let derp = self.clone();
73        let string_len = unsafe {
74            CertNameToStrA(X509_ASN_ENCODING, &derp as *const _, CERT_SIMPLE_NAME_STR | CERT_NAME_STR_REVERSE_FLAG, null_mut(), 0)
75        };
76
77        let mut data: Vec<u8> = vec![0; string_len as usize];
78        unsafe {
79            CertNameToStrA(X509_ASN_ENCODING, &derp as *const _, CERT_SIMPLE_NAME_STR | CERT_NAME_STR_REVERSE_FLAG, data.as_mut_ptr(), self.len);
80        }
81
82        String::from_utf8(data[0..data.len()-1].to_vec()).unwrap_or("(unknown)".to_owned())
83    }
84}
85
86impl Default for CryptoApiBlob {
87    fn default() -> CryptoApiBlob {
88        CryptoApiBlob {
89            len: 0,
90            data: null_mut(),
91        }
92    }
93}
94
95#[repr(C)]
96#[derive(Clone, Debug)]
97pub struct CryptoApiSerialNumberBlob {
98    pub len: u32,
99    pub data: *mut u8,
100}
101
102impl Default for CryptoApiSerialNumberBlob {
103    fn default() -> CryptoApiSerialNumberBlob {
104        CryptoApiSerialNumberBlob {
105            len: 0,
106            data: null_mut(),
107        }
108    }
109}
110
111impl CryptoApiSerialNumberBlob {
112    pub fn from(&mut self, blob: &CryptoApiSerialNumberBlob) {
113        self.len = blob.len;
114        self.data = blob.data;
115    }
116}
117
118impl ToString for CryptoApiSerialNumberBlob {
119    fn to_string(&self) -> String {
120        match self.len {
121            0 => "".to_owned(),
122            _ => {
123                let x = unsafe { from_raw_parts_mut(self.data, self.len as usize) };
124                x.reverse();
125                let x: Vec<String> = x.iter().map(|i| {
126                    format!("{:02x}", i)
127                }).collect();
128                x.join("").to_owned()
129            }
130        }
131    }
132}
133
134#[derive(Debug)]
135#[repr(C)]
136pub struct MsgSignerInfo {
137    pub version: u32,
138    pub issuer: CryptoApiBlob,
139    pub serial_number: CryptoApiSerialNumberBlob,
140    pub hash_algorithm: CryptoAlgorithmIdentifier,
141    pub hash_encryption_algorithm: CryptoAlgorithmIdentifier,
142    pub encrypted_hash: CryptoApiBlob,
143    pub auth_attrs: CryptoAttributes,
144    pub unauth_attrs: CryptoAttributes,
145}
146
147impl MsgSignerInfo {
148}
149
150#[repr(C)]
151pub struct Guid {
152    pub data1: u32,
153    pub data2: u16,
154    pub data3: u16,
155    pub data4: [u8; 8],
156}
157
158impl Guid {
159    pub fn wintrust_action_generic_verify_v2() -> Guid {
160        Guid {
161            data1: 0xaac56b,
162            data2: 0xcd44,
163            data3: 0x11d0,
164            data4: [0x8c,0xc2,0x00,0xc0,0x4f,0xc2,0x95,0xee]
165        }
166    }
167
168    pub fn driver_action_verify() -> Guid {
169        Guid {
170            data1: 0xf750e6c3,
171            data2: 0x38ee,
172            data3: 0x11d1,
173            data4: [0x85,0xe5,0x00,0xc0,0x4f,0xc2,0x95,0xee]
174        }
175    }
176}
177
178#[repr(C)]
179pub struct WinTrustFileInfo
180{
181    pub size: u32,
182    pub file_path: *const u16,
183    pub file_handle: *const u8,
184    pub known_subject_guid: *const Guid,
185}
186
187impl Default for WinTrustFileInfo {
188    fn default() -> WinTrustFileInfo {
189        WinTrustFileInfo {
190            size: size_of::<WinTrustFileInfo>() as u32,
191            file_path: null(),
192            file_handle: null(),
193            known_subject_guid: null(),
194        }
195    }
196}
197
198impl WinTrustFileInfo {
199    pub fn from_path(path: &WideCString) -> WinTrustFileInfo {
200        let mut wtfi = WinTrustFileInfo::default();
201        wtfi.file_path = path.as_ptr();
202        wtfi
203    }
204}
205
206#[repr(C)]
207pub struct WinTrustData
208{
209    pub size: u32,
210    pub policy_callback_data: *const u8,
211    pub sip_client_data: *const u8,
212    pub ui_choice: u32,
213    pub revocation_check: u32,
214    pub union_choice: u32,
215    pub data: *const WinTrustFileInfo,
216    pub state_action: u32,
217    pub wvt_state_data: *const u8,
218    pub url_reference: *const u16,
219    pub prov_flags: u32,
220    pub ui_context: u32,
221    pub signature_settings: *const u8,
222}
223
224impl Default for WinTrustData {
225    fn default() -> WinTrustData {
226        WinTrustData {
227            size: size_of::<WinTrustData>() as u32,
228            policy_callback_data: null(),
229            sip_client_data: null(),
230            ui_choice: WTD_UI_NONE,
231            revocation_check: WTD_REVOKE_NONE,
232            union_choice: WTD_CHOICE_FILE,
233            data: null(),
234            state_action: WTD_STATEACTION_VERIFY,
235            wvt_state_data: null(),
236            url_reference: null(),
237            prov_flags: WTD_CACHE_ONLY_URL_RETRIEVAL,
238            ui_context: 0,
239            signature_settings: null(),
240        }
241    }
242}
243
244pub struct FileHandle {
245    handle: Option<*const u8>,
246    path: Option<String>,
247}
248
249impl FileHandle {
250    pub fn new() -> FileHandle {
251        FileHandle {
252            handle: None,
253            path: None
254        }
255    }
256
257    pub fn handle(&self) -> Option<*const u8> {
258        self.handle
259    }
260
261    pub fn open_file(&mut self, path: &WideCString) {
262        match unsafe {
263            CreateFileW(path.as_ptr(), GENERIC_READ, FILE_SHARE_READ, null(), OPEN_EXISTING, 0, null())
264        } {
265            i if i as usize == 0 => println!("nope!"),
266            f => {
267                self.handle = Some(f);
268                if let Ok(p) = path.to_string() {
269                    self.path = Some(p)
270                }
271            }
272        }
273    }
274
275    pub fn with_file(mut self, path: &WideCString) -> Self {
276        self.open_file(&path);
277        self
278    }
279}
280
281impl Drop for FileHandle {
282    fn drop(&mut self) {
283        if let Some(ref h) = self.handle {
284            unsafe { CloseHandle(*h); }
285        }
286    }
287}
288
289#[repr(C)]
290pub struct CatalogInfo
291{
292    pub size: u32,
293    pub catalog_file: [u16; MAX_PATH],
294}
295
296impl Default for CatalogInfo {
297    fn default() -> CatalogInfo {
298        CatalogInfo {
299            size: size_of::<CatalogInfo>() as u32,
300            catalog_file: [0; MAX_PATH],
301        }
302    }
303}
304
305#[repr(C)]
306#[derive(Debug,Default)]
307pub struct FileTime {
308    u1: u32,
309    u2: u32,
310}
311
312#[repr(C)]
313#[derive(Debug)]
314pub struct CryptoBitBlob {
315    pub size: u32,
316    pub data: *const u8,
317    pub unused_bits: u32,
318}
319
320impl Default for CryptoBitBlob {
321    fn default() -> CryptoBitBlob {
322        CryptoBitBlob {
323            size: 0,
324            data: null(),
325            unused_bits: 0,
326        }
327    }
328}
329
330#[repr(C)]
331#[derive(Debug, Default)]
332pub struct CertPublicKeyInfo {
333    pub algorithm: CryptoAlgorithmIdentifier,
334    pub public_key: CryptoBitBlob,
335}
336
337#[repr(C)]
338#[derive(Debug)]
339pub struct CertInfo {
340    pub version: u32,
341    pub serial_number: CryptoApiSerialNumberBlob,
342    pub signature_algorithm: CryptoAlgorithmIdentifier,
343    pub issuer: CryptoApiBlob,
344    pub not_before: FileTime,
345    pub not_after: FileTime,
346    pub subject: CryptoApiBlob,
347    pub subject_public_key_info: CertPublicKeyInfo,
348    pub issuer_unique_id: CryptoBitBlob,
349    pub subject_unique_id: CryptoBitBlob,
350    pub c_extension: u32,
351    pub rg_extension: *const u8,
352}
353
354impl Default for CertInfo {
355    fn default() -> CertInfo {
356        CertInfo {
357            version: 0,
358            serial_number: Default::default(),
359            signature_algorithm: Default::default(),
360            issuer: Default::default(),
361            not_before: Default::default(),
362            not_after: Default::default(),
363            subject: Default::default(),
364            subject_public_key_info: Default::default(),
365            issuer_unique_id: Default::default(),
366            subject_unique_id: Default::default(),
367            c_extension: 0,
368            rg_extension: null(),
369        }
370    }
371}
372
373pub struct CertStoreContext {
374    context: Option<*const u8>,
375}
376
377impl CertStoreContext {
378    pub fn new(ctx: *const u8) -> CertStoreContext {
379        return match ctx {
380            i if i as usize == 0 => CertStoreContext { context: None },
381            _ => CertStoreContext { context: Some(ctx)}
382        }
383    }
384
385    pub fn context(&self) -> *const u8 {
386        match self.context {
387            Some(ctx) => ctx,
388            None => null()
389        }
390    }
391}
392
393impl Drop for CertStoreContext {
394    fn drop(&mut self) {
395        if let Some(ctx) = self.context {
396            unsafe {
397                CertFreeCertificateContext(ctx);
398            }
399        }
400    }
401}
402
403#[link(name = "crypt32")]
404extern "system" {
405    pub fn CryptQueryObject(
406        object_type: u32,
407        object: *const u8,
408        expected_content_type_flags: u32,
409        expected_format_type_flags: u32,
410        flags: u32,
411        msg_and_cert_encoding_type: *mut u32,
412        content_type: *mut u32,
413        format_type: *mut u32,
414        cert_store: *mut *mut u8,
415        msg: *mut *mut u8,
416        context: *mut *mut u8,
417    ) -> u32;
418
419    pub fn CryptMsgGetParam(
420        crypt_msg: *const u8,
421        param_type: u32,
422        index: u32,
423        data: *mut u8,
424        data_len: *mut u32
425    ) -> u32;
426
427    pub fn CertNameToStrA(
428        cert_encoding_type: u32,
429        name: *const CryptoApiBlob,
430        str_type: u32,
431        psz: *mut u8,
432        csz: u32
433    ) -> u32;
434
435    pub fn CryptCATAdminAcquireContext(
436        admin: *mut *mut u8,
437        action: *const Guid,
438        _: u32
439    ) -> u32;
440
441    pub fn CryptCATAdminCalcHashFromFileHandle(
442        handle: *const u8,
443        hash_length: &mut u32,
444        hash: *mut u8,
445        flags: u32
446    ) -> u32;
447
448    pub fn CryptCATAdminEnumCatalogFromHash(
449        cat_admin: *const u8,
450        hash: *const u8,
451        hash_lenght: u32,
452        flags: u32,
453        prev_cat_info: *mut *mut u8,
454    ) -> *mut u8;
455
456    pub fn CryptCATAdminReleaseCatalogContext(
457        admin: *mut u8,
458        info: *mut u8,
459        flags: u32
460    ) -> u32;
461
462    pub fn CryptCATCatalogInfoFromContext(
463        info_context: *const u8,
464        info: *mut CatalogInfo,
465        flags: u32
466    ) -> u32;
467
468    pub fn CryptCATAdminReleaseContext(
469        hCatAdmin: *const u8,
470        dwFlags: u32
471    ) -> u32;
472
473    pub fn CertFindCertificateInStore(
474        cert_store: *const u8,
475        cert_encoding_type: u32,
476        find_flags: u32,
477        find_type: u32,
478        find_para: *const CertInfo,
479        prev_cert_context: *const u8,
480    ) -> *const u8;
481
482    pub fn CertGetNameStringA(
483        cert_context: *const u8,
484        name_type: u32,
485        flags: u32,
486        type_para: *const u8,
487        name_string: *const u8,
488        name_length: u32
489    ) -> u32;
490
491    pub fn CertFreeCertificateContext(
492        context: *const u8
493    ) -> u32;
494
495    pub fn CertCloseStore(
496        cert_store: *const u8,
497        flags: u32
498    ) -> u32;
499
500    pub fn CryptMsgClose(
501        crypt_msg: *const u8
502    ) -> u32;
503}
504
505#[link(name = "wintrust")]
506extern "system" {
507    pub fn WinVerifyTrust(
508        wnd: *const u8,
509        action_id: *const Guid,
510        wvt_data: *const WinTrustData
511    ) -> u32;
512}
513
514extern "system" {
515    #[allow(dead_code)]
516    pub fn GetLastError() -> u32;
517
518    pub fn CloseHandle(handle: *const u8) -> u32;
519
520    pub fn CreateFileW(
521        file_name: *const u16,
522        desired_access: u32,
523        share_mode: u32,
524        security_attributes: *const u8,
525        creation_disposition: u32,
526        flags_and_attributes: u32,
527        template_file: *const u8,
528    ) -> *const u8;
529}