1#![recursion_limit = "1024"]
2
3#[macro_use]
4extern crate bitflags;
5extern crate byteorder;
6#[macro_use]
7extern crate error_chain;
8#[macro_use]
9extern crate log;
10
11mod errors;
12
13#[allow(non_snake_case, non_camel_case_types, dead_code)]
14#[allow(non_upper_case_globals)]
15mod sys {
16 include!("bindings.rs");
17
18 pub const NULL_HOBJECT: TSS_HOBJECT = 0;
20 pub const NULL_HCONTEXT: TSS_HCONTEXT = 0;
21 pub const NULL_HPCRS: TSS_HPCRS = 0;
22 pub const NULL_HKEY: TSS_HKEY = 0;
23 pub const NULL_HTPM: TSS_HTPM = 0;
24 pub const NULL_HPOLICY: TSS_HPOLICY = 0;
25
26 pub const TSS_SUCCESS: TSS_RESULT = 0;
28
29 pub const TSS_ERROR_LAYER: u32 = 0x3000;
31
32 pub const NO_FLAG: TSS_FLAG = 0;
34
35 pub const TSS_TPM_PCR_DEFAULT: TSS_FLAG = 0x0;
37 pub const TSS_TPM_PCR_INFO: TSS_FLAG = 0x1;
38 pub const TSS_TPM_PCR_INFO_LONG: TSS_FLAG = 0x2;
39 pub const TSS_TPM_PCR_INFO_SHORT: TSS_FLAG = 0x3;
40
41 pub const TSS_WELL_KNOWN_SECRET: &'static [u8] = &[0; 20];
43
44 pub const TPM_TAG_NV_ATTRIBUTES: TPM_STRUCTURE_TAG = 0x0017;
46 pub const TPM_TAG_NV_DATA_PUBLIC: TPM_STRUCTURE_TAG = 0x0018;
47}
48
49use byteorder::{BigEndian, ReadBytesExt};
50pub use errors::{Error, ErrorKind, Result};
51pub use errors::tpm::ErrorKind as TpmErrorKind;
52use std::io::{Cursor, Read};
53use std::ptr;
54
55macro_rules! tss_tpm_err(
56 ($kind:path) => ( Err(ErrorKind::Tpm($kind).into()) )
57);
58
59macro_rules! tss_tsp_err(
60 ($kind:path) => ( Err(ErrorKind::Tsp($kind).into()) )
61);
62
63fn tss_err(err: sys::TSS_RESULT) -> Result<()> {
64 match err {
66 sys::TSS_SUCCESS => Ok(()),
68 val => {
70 match val & sys::TSS_ERROR_LAYER {
71 sys::TSS_LAYER_TPM => {
72 match val & sys::TSS_MAX_ERROR {
73 0x01 => tss_tpm_err!(errors::tpm::ErrorKind::AuthFail),
74 0x02 => tss_tpm_err!(errors::tpm::ErrorKind::BadIndex),
75 0x03 => tss_tpm_err!(errors::tpm::ErrorKind::BadParam),
76 0x04 => tss_tpm_err!(errors::tpm::ErrorKind::AuditFail),
77 0x05 => tss_tpm_err!(errors::tpm::ErrorKind::ClearDisabled),
78 0x06 => tss_tpm_err!(errors::tpm::ErrorKind::Deactivated),
79 0x07 => tss_tpm_err!(errors::tpm::ErrorKind::Disabled),
80 0x08 => tss_tpm_err!(errors::tpm::ErrorKind::DisabledCmd),
81 0x09 => tss_tpm_err!(errors::tpm::ErrorKind::Fail),
82 0x0A => tss_tpm_err!(errors::tpm::ErrorKind::BadOrdinal),
83 0x11 => tss_tpm_err!(errors::tpm::ErrorKind::NoSpace),
84 0x12 => tss_tpm_err!(errors::tpm::ErrorKind::NoSrk),
85 0x14 => tss_tpm_err!(errors::tpm::ErrorKind::OwnerSet),
86 0x17 => tss_tpm_err!(errors::tpm::ErrorKind::Size),
87 0x23 => tss_tpm_err!(errors::tpm::ErrorKind::NoEndorsement),
88 0x3b => tss_tpm_err!(errors::tpm::ErrorKind::AuthConflict),
89 0x3e => tss_tpm_err!(errors::tpm::ErrorKind::PermissionReadOnly),
90 0x3f => tss_tpm_err!(errors::tpm::ErrorKind::PermissionNoWrite),
91 err => Err(ErrorKind::Tpm(errors::tpm::ErrorKind::NotWrapped(err)).into()),
92 }
93 }
94 sys::TSS_LAYER_TDDL => Err(ErrorKind::Tddl(err).into()),
95 sys::TSS_LAYER_TCS => Err(ErrorKind::Tcs(err).into()),
96 sys::TSS_LAYER_TSP => {
97 match val & sys::TSS_MAX_ERROR {
98 0x003 => tss_tsp_err!(errors::tsp::ErrorKind::BadParam),
99 0x011 => tss_tsp_err!(errors::tsp::ErrorKind::CommFailure),
100 0x109 => tss_tsp_err!(errors::tsp::ErrorKind::InvalidAttributeFlag),
101 0x10A => tss_tsp_err!(errors::tsp::ErrorKind::InvalidAttributeSubFlag),
102 0x116 => tss_tsp_err!(errors::tsp::ErrorKind::PolicyNoSecret),
103 0x126 => tss_tsp_err!(errors::tsp::ErrorKind::InvalidHandle),
104 0x13B => tss_tsp_err!(errors::tsp::ErrorKind::NvAreaExists),
105 0x13C => tss_tsp_err!(errors::tsp::ErrorKind::NvAreaNotExists),
106 err => Err(ErrorKind::Tsp(errors::tsp::ErrorKind::NotWrapped(err)).into()),
107 }
108 }
109 _ => Err(ErrorKind::Unknown(err).into()),
110 }
111 }
112 }
113}
114
115#[derive(Debug)]
116pub struct Context {
117 inner: sys::TSS_HCONTEXT,
118}
119
120impl Drop for Context {
121 fn drop(&mut self) {
122 trace!("Tspi_Context_FreeMemory({})", self.inner);
123 unsafe {
124 sys::Tspi_Context_FreeMemory(self.inner, ptr::null_mut());
125 }
126 trace!("Tspi_Context_Close({})", self.inner);
127 unsafe {
128 sys::Tspi_Context_Close(self.inner);
129 }
130 }
131}
132
133impl Context {
134 pub fn new() -> Result<Self> {
135 let mut ctx = sys::NULL_HCONTEXT;
136
137 tss_err(unsafe { sys::Tspi_Context_Create(&mut ctx) })?;
139 trace!("Tspi_Context_Create() = {}", ctx);
140 Ok(Context { inner: ctx })
141 }
142
143 pub fn connect(self, dest: Connect) -> Result<ConnectedContext> {
144
145 let result = match dest {
147 Connect::Host(host) => {
148 let mut dest = host.encode_utf16().collect::<Vec<u16>>();
149 dest.push(0 as u16);
151 unsafe { sys::Tspi_Context_Connect(self.inner, dest.as_mut_ptr()) }
152 }
153 Connect::Localhost => unsafe { sys::Tspi_Context_Connect(self.inner, ptr::null_mut()) },
154 };
155
156 trace!("Tspi_Context_Connect({}, ...) = {:?}", self.inner, result);
157
158 tss_err(result)?;
159
160 let mut tpm = sys::NULL_HOBJECT;
161
162 tss_err(unsafe { sys::Tspi_Context_GetTpmObject(self.inner, &mut tpm) })?;
163 trace!("Tspi_Context_GetTpmObject({}) = TPMObject({})",
164 self.inner,
165 tpm);
166 let obj = Tpm { inner: tpm };
167
168 Ok(ConnectedContext {
169 inner: self,
170 tpm: obj,
171 })
172 }
173}
174
175pub enum Connect<'a> {
176 Localhost,
177 Host(&'a str),
178}
179
180#[derive(Debug)]
181pub struct ConnectedContext {
182 inner: Context,
183 tpm: Tpm,
184}
185
186impl ConnectedContext {
187 pub fn get_tpm(&self) -> &Tpm {
188 &self.tpm
189 }
190}
191
192bitflags! {
193 pub struct PcrLocality: sys::TPM_LOCALITY_SELECTION {
194 const PCR_LOCALITY_0 = 0b00001;
195 const PCR_LOCALITY_1 = 0b00010;
196 const PCR_LOCALITY_2 = 0b00100;
197 const PCR_LOCALITY_3 = 0b01000;
198 const PCR_LOCALITY_4 = 0b10000;
199 const PCR_LOCALITY_ALL = PCR_LOCALITY_0.bits
200 | PCR_LOCALITY_1.bits
201 | PCR_LOCALITY_2.bits
202 | PCR_LOCALITY_3.bits
203 | PCR_LOCALITY_4.bits;
204 }
205}
206
207bitflags! {
208 pub struct NvPermissions: sys::TPM_NV_PER_ATTRIBUTES {
209 const TPM_NV_PER_READ_STCLEAR = (1 << 31);
211 const TPM_NV_PER_AUTHREAD = (1 << 18);
212 const TPM_NV_PER_OWNERREAD = (1 << 17);
213 const TPM_NV_PER_PPREAD = (1 << 16);
214 const TPM_NV_PER_GLOBALLOCK = (1 << 15);
215 const TPM_NV_PER_WRITE_STCLEAR = (1 << 14);
216 const TPM_NV_PER_WRITEDEFINE = (1 << 13);
217 const TPM_NV_PER_WRITEALL = (1 << 12);
218 const TPM_NV_PER_AUTHWRITE = (1 << 2);
219 const TPM_NV_PER_OWNERWRITE = (1 << 1);
220 const TPM_NV_PER_PPWRITE = (1 << 0);
221 }
222}
223
224#[derive(Clone, Debug)]
225pub struct PcrInfoShort {
226 pub locality: PcrLocality,
227 pub pcr_selection: Vec<u8>,
228 digest: Vec<u8>,
229}
230
231fn read_nv_data_public<R: Read>(mut rdr: R, index: u32, obj: NvRamObj) -> Result<NvRamArea> {
234 let tag = rdr.read_u16::<BigEndian>()?;
235 let nv_index = rdr.read_u32::<BigEndian>()?;
236 let pcr_read = read_pcr_info_short(&mut rdr)?;
237 let pcr_write = read_pcr_info_short(&mut rdr)?;
238 let attrib_tag = rdr.read_u16::<BigEndian>()?;
239 let attrib = NvPermissions::from_bits_truncate(rdr.read_u32::<BigEndian>()?);
240 let read_st_clear = rdr.read_u8()?;
241 let write_st_clear = rdr.read_u8()?;
242 let write_define = rdr.read_u8()?;
243 let data_size = rdr.read_u32::<BigEndian>()?;
244
245 ensure!(tag == sys::TPM_TAG_NV_DATA_PUBLIC,
246 ErrorKind::Decode(format!("Did not receive NV_DATA_PUBLIC tag: {:X}", tag)));
247
248 ensure!(attrib_tag == sys::TPM_TAG_NV_ATTRIBUTES,
249 ErrorKind::Decode(format!("Did not receive NV_ATTRIBUTES tag: {:X}", attrib_tag)));
250
251 ensure!(nv_index == index,
252 ErrorKind::Decode(format!("Got invalid NVRAM index {:X} vs requested {:X}",
253 nv_index,
254 index)));
255
256 Ok(NvRamArea {
257 obj: obj,
258 policy: None,
259 index: nv_index,
260 pcr_read: pcr_read,
261 pcr_write: pcr_write,
262 perms: attrib,
263 read_st_clear: (read_st_clear > 0),
264 write_st_clear: (write_st_clear > 0),
265 write_define: (write_define > 0),
266 size: data_size,
267 })
268}
269
270#[derive(Debug)]
271pub struct NvRamArea<'ctx> {
272 obj: NvRamObj<'ctx>,
273 policy: Option<PolicyUsage<'ctx>>,
274 pub index: u32,
275 pub pcr_read: PcrInfoShort,
276 pub pcr_write: PcrInfoShort,
277 pub perms: NvPermissions,
278 pub read_st_clear: bool,
279 pub write_st_clear: bool,
280 pub write_define: bool,
281 pub size: u32,
282}
283
284impl<'ctx> NvRamArea<'ctx> {
285 pub fn define(ctx: &'ctx ConnectedContext,
287 index: u32,
288 size: u32,
289 perms: NvPermissions,
290 read: PcrLocality,
291 write: PcrLocality)
292 -> Result<NvRamArea<'ctx>> {
293 let tpm = ctx.get_tpm();
295
296 let nv_obj = NvRamObj::get(ctx, index)?
297 .attr(sys::TSS_TSPATTRIB_NV_DATASIZE, sys::NO_FLAG, size)?
298 .attr(sys::TSS_TSPATTRIB_NV_PERMISSIONS,
299 sys::NO_FLAG,
300 perms.bits as u32)?;
301
302 let read_pcr = PcrComposite::new(ctx)?.locality(read)?;
303 let write_pcr = PcrComposite::new(ctx)?.locality(write)?;
304
305 trace!("Tspi_NV_DefineSpace({}, {:?}, {:?}) for 0x{:08X} of size {}",
306 nv_obj.inner,
307 read,
308 write,
309 index,
310 size);
311 tss_err(unsafe {
312 sys::Tspi_NV_DefineSpace(nv_obj.inner, read_pcr.inner, write_pcr.inner)
313 })?;
314
315 read_nv_data_public(tpm.get_nv_data(index)?, index, nv_obj)
316 }
317
318 pub fn get(ctx: &'ctx ConnectedContext, index: u32) -> Result<NvRamArea<'ctx>> {
320 let tpm = ctx.get_tpm();
322
323 let nv_obj = NvRamObj::get(ctx, index)?;
324 read_nv_data_public(tpm.get_nv_data(index)?, index, nv_obj)
325 }
326
327 pub fn secret(mut self, secret: Secret) -> Result<Self> {
329 let policy = PolicyUsage::new(self.obj.ctx)?.secret(secret)?;
330 policy.assign(self.obj.inner)?;
331 self.policy = Some(policy);
332 Ok(self)
333 }
334
335 pub fn write(&self, offset: usize, data: &[u8]) -> Result<()> {
337 ensure!((offset + data.len()) as u32 <= self.size,
338 ErrorKind::BadSize(format!("offset {} + write size {} greater than \
339 NVRAM area size {}",
340 offset,
341 data.len(),
342 self.size)));
343
344 let chunk_size = 512;
347 let mut pos = offset;
348 for chunk in data.chunks(chunk_size) {
349 self.obj.write_chunk(pos as u32, chunk)?;
350 pos += chunk_size;
351 }
352
353 Ok(())
354 }
355
356 pub fn release(self) -> Result<()> {
358 let index = self.index;
359 let ret = self.obj.release();
360
361 if let Err(ref e) = ret {
362 debug!("Failed to delete NVRAM area 0x{:08}: {}", index, e);
363 }
364 ret
365 }
366}
367
368fn ptr_to_owned_cursor(buf: *mut sys::BYTE, len: usize) -> Cursor<Vec<u8>> {
370 let mut dst = Vec::with_capacity(len);
371
372 unsafe {
373 dst.set_len(len);
374 ptr::copy(buf, dst.as_mut_ptr(), len);
375 };
376
377 Cursor::new(dst)
378}
379
380fn read_pcr_info_short<T: Read>(rdr: &mut T) -> Result<PcrInfoShort> {
382
383 let pcr_select_size = rdr.read_u16::<BigEndian>()?;
384 let mut pcr_select = vec![0; pcr_select_size as usize];
385 rdr.read_exact(&mut pcr_select)?;
386 let locality = rdr.read_u8()?;
387 let mut digest = vec![0; sys::TPM_SHA1_160_HASH_LEN as usize];
388 rdr.read_exact(&mut digest)?;
389
390 Ok(PcrInfoShort {
391 locality: PcrLocality::from_bits_truncate(locality),
392 pcr_selection: pcr_select,
393 digest: digest,
394 })
395
396}
397
398#[derive(Clone, Debug)]
399enum TpmCap {
400 NvIndex(u32),
401 Owner,
402}
403
404#[derive(Debug)]
405pub struct Tpm {
406 inner: sys::TSS_HTPM,
407}
408
409impl Tpm {
410 pub fn is_owned(&self) -> Result<bool> {
412 let mut rdr = self.get_cap(TpmCap::Owner)?;
413 match rdr.read_u8()? {
414 0 => Ok(false),
415 _ => Ok(true),
416 }
417 }
418
419 pub fn is_enabled(&self) -> Result<bool> {
421 self.get_status(sys::TSS_TPMSTATUS_DISABLED).map(|v| !v)
423 }
424
425 pub fn is_active(&self) -> Result<bool> {
427 self.get_status(sys::TSS_TPMSTATUS_DEACTIVATED).map(|v| !v)
429 }
430
431 fn get_nv_data(&self, index: u32) -> Result<Cursor<Vec<u8>>> {
432 self.get_cap(TpmCap::NvIndex(index))
433 }
434
435 fn get_cap(&self, cap: TpmCap) -> Result<Cursor<Vec<u8>>> {
436 let idx_len = ::std::mem::size_of::<u32>() as u32;
438
439 let mut variable: u32 = sys::TSS_TPMCAP_PROP_OWNER;
441
442 let (tpmcap, param) = match cap {
443 TpmCap::NvIndex(index) => {
444 variable = index;
445 (sys::TSS_TPMCAP_NV_INDEX, &mut variable as *mut u32 as *mut u8)
446 }
447 TpmCap::Owner => (sys::TSS_TPMCAP_PROPERTY, &mut variable as *mut u32 as *mut u8),
448 };
449
450 let mut result_len = 0;
451 let mut result: *mut sys::BYTE = ptr::null_mut();
452
453 trace!("Tspi_TPM_GetCapability({}, 0x{:X}, {:?}, ...)",
454 self.inner,
455 tpmcap,
456 cap);
457 tss_err(unsafe {
458 sys::Tspi_TPM_GetCapability(self.inner,
459 tpmcap,
460 idx_len,
461 param,
462 &mut result_len,
463 &mut result)
464 })?;
465
466 Ok(ptr_to_owned_cursor(result, result_len as usize))
467 }
468
469 fn get_status(&self, status: sys::TSS_FLAG) -> Result<bool> {
470 trace!("Tspi_TPM_GetStatus({}, 0x{:08X}, ...)", self.inner, status);
471 let mut data: i8 = 0;
472
473 tss_err(unsafe { sys::Tspi_TPM_GetStatus(self.inner, status, &mut data) })?;
474
475 match data {
476 0 => Ok(false),
477 _ => Ok(true),
478 }
479 }
480
481 pub fn set_secret(&self, secret: Secret) -> Result<()> {
482 set_secret_helper(self.inner, secret)
483 }
484
485 pub fn take_ownership(&self, srk: Srk) -> Result<()> {
486 trace!("Tspi_TPM_TakeOwnership({}, {}, NULL)",
487 self.inner,
488 srk.inner);
489 tss_err(unsafe { sys::Tspi_TPM_TakeOwnership(self.inner, srk.inner, sys::NULL_HKEY) })?;
490 Ok(())
491 }
492}
493
494#[derive(Debug)]
495pub enum Secret<'a> {
496 WellKnown,
497 Key(&'a [u8]),
498}
499
500fn set_secret_helper(obj: sys::TSS_HOBJECT, secret: Secret) -> Result<()> {
501 let mut policy = sys::NULL_HPOLICY;
502
503 tss_err(unsafe { sys::Tspi_GetPolicyObject(obj, sys::TSS_POLICY_USAGE, &mut policy) })?;
504 trace!("Tspi_GetPolicyObject({}, TSS_POLICY_USAGE) = PolicyObject({})",
505 obj,
506 policy);
507
508 let (mode, key) = match secret {
509 Secret::WellKnown => (sys::TSS_SECRET_MODE_SHA1, sys::TSS_WELL_KNOWN_SECRET),
510 Secret::Key(k) => (sys::TSS_SECRET_MODE_PLAIN, k),
511 };
512
513 trace!("Tspi_Policy_SetSecret({}, {:?}, ...)", policy, secret);
514 tss_err(unsafe { sys::Tspi_Policy_SetSecret(policy, mode, key.len() as u32, key.as_ptr()) })?;
515 Ok(())
516}
517
518macro_rules! tspi_obj {
519 ($(#[$attr:meta])* struct $obj:ident {
520 const flag = $flag:expr;
521 const sub_flag = $sub_flag:expr;
522 }) =>
523 (
524 $(#[$attr])*
525 struct $obj<'ctx> {
526 ctx: &'ctx ConnectedContext,
527 inner: sys::TSS_HOBJECT,
528 }
529
530 __impl_tspi_obj!($obj, $flag, $sub_flag);
531 );
532
533 ($(#[$attr:meta])* pub struct $obj:ident {
534 const flag = $flag:expr;
535 const sub_flag = $sub_flag:expr;
536 }) =>
537 (
538 $(#[$attr])*
539 pub struct $obj<'ctx> {
540 ctx: &'ctx ConnectedContext,
541 inner: sys::TSS_HOBJECT,
542 }
543
544 __impl_tspi_obj!($obj, $flag, $sub_flag);
545 );
546}
547
548macro_rules! __impl_tspi_obj {
549 ($obj:ident, $flag:expr, $sub_flag:expr) =>
550 (
551 impl<'ctx> Drop for $obj<'ctx> {
552 fn drop(&mut self) {
553 trace!("Tspi_Context_CloseObject({}, {}) Object({}, {})",
554 self.ctx.inner.inner,
555 self.inner,
556 stringify!($flag),
557 stringify!($sub_flag));
558 unsafe {
559 sys::Tspi_Context_CloseObject(self.ctx.inner.inner, self.inner);
560 }
561 }
562 }
563
564 impl<'ctx> $obj<'ctx> {
565 fn new(ctx: &'ctx ConnectedContext) -> Result<Self> {
566 let mut obj = sys::NULL_HOBJECT;
567
568 tss_err(unsafe {
569 sys::Tspi_Context_CreateObject(ctx.inner.inner, $flag, $sub_flag, &mut obj)
570 })?;
571 trace!("Tspi_Context_CreateObject({}, {}, {}) = Object({})",
572 ctx.inner.inner,
573 stringify!($flag),
574 stringify!($sub_flag),
575 obj);
576
577 Ok($obj {
578 ctx: &ctx,
579 inner: obj,
580 })
581 }
582 }
583 );
584}
585
586tspi_obj!(
587 struct PcrComposite {
588 const flag = sys::TSS_OBJECT_TYPE_PCRS;
589 const sub_flag = sys::TSS_TPM_PCR_INFO_SHORT;
590 });
591
592impl<'ctx> PcrComposite<'ctx> {
593 fn locality(self, locality: PcrLocality) -> Result<Self> {
594 trace!("Tspi_PcrComposite_SetPcrLocality({}, {:?})",
595 self.inner,
596 locality);
597 tss_err(unsafe {
598 sys::Tspi_PcrComposite_SetPcrLocality(self.inner, locality.bits() as u32)
599 })
600 .map(|_| self)
601 }
602}
603
604tspi_obj!(
605 pub struct Srk {
606 const flag = sys::TSS_OBJECT_TYPE_RSAKEY;
607 const sub_flag = sys::TSS_KEY_TSP_SRK + sys::TSS_KEY_AUTHORIZATION;
608 });
609
610impl<'ctx> Srk<'ctx> {
611 pub fn get(ctx: &'ctx ConnectedContext) -> Result<Self> {
613 Srk::new(ctx)
614 }
615
616 pub fn secret(self, secret: Secret) -> Result<Self> {
618 set_secret_helper(self.inner, secret).map(|_| self)
619 }
620}
621
622tspi_obj!(
623 #[derive(Debug)]
624 pub struct NvRamObj {
625 const flag = sys::TSS_OBJECT_TYPE_NV;
626 const sub_flag = sys::NO_FLAG;
627 });
628
629impl<'ctx> NvRamObj<'ctx> {
630 fn get(ctx: &'ctx ConnectedContext, index: u32) -> Result<NvRamObj<'ctx>> {
631 NvRamObj::new(ctx)?.attr(sys::TSS_TSPATTRIB_NV_INDEX, sys::NO_FLAG, index)
632 }
633
634 fn attr(self, flag: sys::TSS_FLAG, sub_flag: sys::TSS_FLAG, value: u32) -> Result<Self> {
635 trace!("Tspi_SetAttribUint32({}, {:X}, {:X}, 0x{:08X})",
636 self.inner,
637 flag,
638 sub_flag,
639 value);
640 tss_err(unsafe { sys::Tspi_SetAttribUint32(self.inner, flag, sub_flag, value) })
641 .map(|_| self)
642 }
643
644 fn write_chunk(&self, offset: u32, data: &[u8]) -> Result<()> {
645 trace!("Tspi_NV_WriteValue({}, offset={}, len={}, data=[...])",
646 self.inner,
647 offset,
648 data.len());
649 tss_err(unsafe {
650 sys::Tspi_NV_WriteValue(self.inner, offset, data.len() as u32, data.as_ptr())
651 })
652 }
653
654 fn release(self) -> Result<()> {
655 trace!("Tspi_NV_ReleaseSpace({})", self.inner);
656 tss_err(unsafe { sys::Tspi_NV_ReleaseSpace(self.inner) })
657 }
658}
659
660tspi_obj!(
661 #[derive(Debug)]
662 struct PolicyUsage {
663 const flag = sys::TSS_OBJECT_TYPE_POLICY;
664 const sub_flag = sys::TSS_POLICY_USAGE;
665 });
666
667impl<'ctx> PolicyUsage<'ctx> {
668 fn secret(self, secret: Secret) -> Result<Self> {
669 let (mode, key) = match secret {
670 Secret::WellKnown => (sys::TSS_SECRET_MODE_SHA1, sys::TSS_WELL_KNOWN_SECRET),
671 Secret::Key(k) => (sys::TSS_SECRET_MODE_PLAIN, k),
672 };
673 let mut key = key.to_owned();
674
675 trace!("Tspi_Policy_SetSecret({}, {})",
676 self.inner,
677 stringify!(mode));
678 tss_err(unsafe {
679 sys::Tspi_Policy_SetSecret(self.inner, mode, key.len() as u32, key.as_mut_ptr())
680 })
681 .map(|_| self)
682 }
683
684 fn assign(&self, target: sys::TSS_HOBJECT) -> Result<()> {
685 trace!("Tspi_Policy_AssignToObject({}, {})", self.inner, target);
686 tss_err(unsafe { sys::Tspi_Policy_AssignToObject(self.inner, target) })
687 }
688}