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}