tss_tspi/
lib.rs

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    // from trousers_types.h
19    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    // from tss/tss_error.h
27    pub const TSS_SUCCESS: TSS_RESULT = 0;
28
29    // from trousers_types.h
30    pub const TSS_ERROR_LAYER: u32 = 0x3000;
31
32    // helper to avoid 0 as TSS_FLAG everywhere
33    pub const NO_FLAG: TSS_FLAG = 0;
34
35    // no defines for these in the headers they instead are defined in comments
36    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    // this never got pulled in
42    pub const TSS_WELL_KNOWN_SECRET: &'static [u8] = &[0; 20];
43
44    // from tss/tpm.h
45    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 against the error returned
65    match err {
66        // do nothing for success
67        sys::TSS_SUCCESS => Ok(()),
68        // any error in the valid error range needs to be taken apart by layer
69        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        // create our context
138        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        // connect to trousers (in theory)
146        let result = match dest {
147            Connect::Host(host) => {
148                let mut dest = host.encode_utf16().collect::<Vec<u16>>();
149                // null terminate
150                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        // from tss/tpm.h
210        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
231/// reads the byte stream from the TPM that contains details about this NVRAM area
232/// corresponds to the C function getNVDataPublic()
233fn 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    /// create an NVRAM area
286    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        // get a reference to the TPM
294        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    /// get a reference to a NVRAM area
319    pub fn get(ctx: &'ctx ConnectedContext, index: u32) -> Result<NvRamArea<'ctx>> {
320        // get a reference to the TPM
321        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    /// assign a secret to a specific NVRAM arex
328    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    /// write data to a specific NVRAM area
336    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        // due to a bug with some hardware not supporting 1024 byte writes we'll just do
345        // a 512 byte write to be safe
346        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    /// delete the NVRAM area
357    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
368/// copies a pointer we got back from C code and converts it to a Cursor of bytes
369fn 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
380/// reads sys::TPM_PCR_INFO_SHORT and returns PcrInfoShort
381fn 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    /// checks if the TPM is owned or not
411    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    /// check if the TPM is enabled or not
420    pub fn is_enabled(&self) -> Result<bool> {
421        // invert the logic of the flag since we get back true if its disabled
422        self.get_status(sys::TSS_TPMSTATUS_DISABLED).map(|v| !v)
423    }
424
425    /// check if the TPM is active or not
426    pub fn is_active(&self) -> Result<bool> {
427        // invert the logic of the flag since we get back true if its disabled
428        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        // size of our subarea (param)
437        let idx_len = ::std::mem::size_of::<u32>() as u32;
438
439        // variable kept in scope for the call below
440        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    /// get a reference to the Storage Root Key object
612    pub fn get(ctx: &'ctx ConnectedContext) -> Result<Self> {
613        Srk::new(ctx)
614    }
615
616    /// set the necessary secret to utilize the Storage Root Key
617    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}