1
1
// Copyright 2020 Contributors to the Parsec project.
2
2
// SPDX-License-Identifier: Apache-2.0
3
3
4
- use std:: { convert:: TryFrom , io:: Read } ;
4
+ use std:: {
5
+ convert:: { TryFrom , TryInto } ,
6
+ io:: Read ,
7
+ } ;
5
8
6
9
use crate :: {
7
10
constants:: { tss:: * , CapabilityType , PropertyTag } ,
8
- handles:: { NvIndexHandle , NvIndexTpmHandle , TpmHandle } ,
11
+ handles:: { AuthHandle , NvIndexHandle , NvIndexTpmHandle , TpmHandle } ,
9
12
interface_types:: resource_handles:: NvAuth ,
10
13
structures:: { CapabilityData , MaxNvBuffer , Name , NvPublic } ,
11
14
Context , Error , Result , WrapperErrorKind ,
@@ -81,16 +84,25 @@ pub fn list(context: &mut Context) -> Result<Vec<(NvPublic, Name)>> {
81
84
/// This builder exposes the ability to determine how a [`NvReaderWriter`] is opened, and is typically used by
82
85
/// calling [`NvOpenOptions::new`], chaining method calls to set each option and then calling [`NvOpenOptions::open`].
83
86
#[ derive( Debug , Clone , Default ) ]
84
- // The type is going to get more complex in the future
85
- # [ allow ( missing_copy_implementations ) ]
86
- pub struct NvOpenOptions { }
87
+ pub struct NvOpenOptions {
88
+ nv_public : Option < NvPublic > ,
89
+ }
87
90
88
91
impl NvOpenOptions {
89
92
/// Creates a new blank set of options for opening a non-volatile storage index
90
93
///
91
94
/// All options are initially set to `false`/`None`.
92
95
pub fn new ( ) -> Self {
93
- Self { }
96
+ Self { nv_public : None }
97
+ }
98
+
99
+ /// Sets the public attributes to use when creating the non-volatile storage index
100
+ ///
101
+ /// If the public attributes are `None` then the non-volatile storage index will be opened or otherwise
102
+ /// it will be created.
103
+ pub fn with_nv_public ( & mut self , nv_public : Option < NvPublic > ) -> & mut Self {
104
+ self . nv_public = nv_public;
105
+ self
94
106
}
95
107
96
108
/// Opens a non-volatile storage index using the options specified by `self`
@@ -106,13 +118,30 @@ impl NvOpenOptions {
106
118
. get_tpm_property ( PropertyTag :: NvBufferMax ) ?
107
119
. unwrap_or ( MaxNvBuffer :: MAX_SIZE as u32 ) as usize ;
108
120
109
- let nv_idx = TpmHandle :: NvIndex ( nv_index_handle) ;
110
- let nv_idx = context
111
- . execute_without_session ( |ctx| ctx. tr_from_tpm_public ( nv_idx) ) ?
112
- . into ( ) ;
113
- let data_size = context
114
- . execute_without_session ( |ctx| ctx. nv_read_public ( nv_idx) )
115
- . map ( |( nvpub, _) | nvpub. data_size ( ) ) ?;
121
+ let ( data_size, nv_idx) = match & self . nv_public {
122
+ None => {
123
+ let nv_idx = TpmHandle :: NvIndex ( nv_index_handle) ;
124
+ let nv_idx = context
125
+ . execute_without_session ( |ctx| ctx. tr_from_tpm_public ( nv_idx) ) ?
126
+ . into ( ) ;
127
+ (
128
+ context
129
+ . execute_without_session ( |ctx| ctx. nv_read_public ( nv_idx) )
130
+ . map ( |( nvpub, _) | nvpub. data_size ( ) ) ?,
131
+ nv_idx,
132
+ )
133
+ }
134
+ Some ( nv_public) => {
135
+ if nv_public. nv_index ( ) != nv_index_handle {
136
+ return Err ( Error :: WrapperError ( WrapperErrorKind :: InconsistentParams ) ) ;
137
+ }
138
+ let auth_handle = AuthHandle :: from ( auth_handle) ;
139
+ (
140
+ nv_public. data_size ( ) ,
141
+ context. nv_define_space ( auth_handle. try_into ( ) ?, None , nv_public. clone ( ) ) ?,
142
+ )
143
+ }
144
+ } ;
116
145
117
146
Ok ( NvReaderWriter {
118
147
context,
@@ -168,6 +197,61 @@ impl Read for NvReaderWriter<'_> {
168
197
}
169
198
}
170
199
200
+ impl std:: io:: Write for NvReaderWriter < ' _ > {
201
+ fn write ( & mut self , buf : & [ u8 ] ) -> std:: io:: Result < usize > {
202
+ if self . data_size < self . offset {
203
+ return Ok ( 0 ) ;
204
+ }
205
+
206
+ let desired_size = std:: cmp:: min ( buf. len ( ) , self . data_size - self . offset ) ;
207
+ let size = std:: cmp:: min ( self . buffer_size , desired_size) as u16 ;
208
+
209
+ let data = buf[ 0 ..size. into ( ) ]
210
+ . try_into ( )
211
+ . map_err ( |e| std:: io:: Error :: new ( std:: io:: ErrorKind :: Other , e) ) ?;
212
+ self . context
213
+ . nv_write ( self . auth_handle , self . nv_idx , data, self . offset as u16 )
214
+ . map_err ( |e| std:: io:: Error :: new ( std:: io:: ErrorKind :: Other , e) ) ?;
215
+ self . offset += size as usize ;
216
+
217
+ Ok ( size. into ( ) )
218
+ }
219
+
220
+ fn flush ( & mut self ) -> std:: io:: Result < ( ) > {
221
+ // Data isn't buffered
222
+ Ok ( ( ) )
223
+ }
224
+ }
225
+
226
+ impl std:: io:: Seek for NvReaderWriter < ' _ > {
227
+ fn seek ( & mut self , pos : std:: io:: SeekFrom ) -> std:: io:: Result < u64 > {
228
+ let inv_input_err = |_| {
229
+ std:: io:: Error :: new (
230
+ std:: io:: ErrorKind :: InvalidInput ,
231
+ "invalid seek to a negative or overflowing position" ,
232
+ )
233
+ } ;
234
+ let ( base, offset) = match pos {
235
+ std:: io:: SeekFrom :: Start ( offset) => {
236
+ ( usize:: try_from ( offset) . map_err ( inv_input_err) ?, 0 )
237
+ }
238
+ std:: io:: SeekFrom :: End ( offset) => ( self . data_size , offset) ,
239
+ std:: io:: SeekFrom :: Current ( offset) => ( self . offset , offset) ,
240
+ } ;
241
+ let new_offset = i64:: try_from ( base)
242
+ . map_err ( inv_input_err) ?
243
+ . checked_add ( offset)
244
+ . ok_or_else ( || {
245
+ std:: io:: Error :: new (
246
+ std:: io:: ErrorKind :: InvalidInput ,
247
+ "invalid seek to a negative or overflowing position" ,
248
+ )
249
+ } ) ?;
250
+ self . offset = new_offset. try_into ( ) . map_err ( inv_input_err) ?;
251
+ self . offset . try_into ( ) . map_err ( inv_input_err)
252
+ }
253
+ }
254
+
171
255
impl Drop for NvReaderWriter < ' _ > {
172
256
fn drop ( & mut self ) {
173
257
let mut obj_handle = self . nv_idx . into ( ) ;
0 commit comments