1 // Copyright © 2022, Microsoft Corporation 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 // 5 6 #[macro_use] 7 extern crate log; 8 9 pub mod emulator; 10 pub mod socket; 11 12 use anyhow::anyhow; 13 use thiserror::Error; 14 15 pub const TPM_CRB_BUFFER_MAX: usize = 3968; // 0x1_000 - 0x80 16 pub const TPM_SUCCESS: u32 = 0x0; 17 18 /* 19 * Structures required to process Request and Responses of Control commands 20 * used by control channel over UNIX socket interface 21 * 22 * All messages contain big-endian data. 23 * 24 * Reference: https://github.com/stefanberger/swtpm/blob/master/man/man3/swtpm_ioctls.pod 25 */ 26 #[derive(Debug, Clone, Copy)] 27 pub enum Commands { 28 CmdGetCapability = 1, 29 CmdInit, 30 CmdShutdown, 31 CmdGetTpmEstablished, 32 CmdSetLocality, 33 CmdHashStart, 34 CmdHashData, 35 CmdHashEnd, 36 CmdCancelTpmCmd, 37 CmdStoreVolatile, 38 CmdResetTpmEstablished, 39 CmdGetStateBlob, 40 CmdSetStateBlob, 41 CmdStop, 42 CmdGetConfig, 43 CmdSetDatafd, 44 CmdSetBufferSize, 45 } 46 47 #[derive(Error, Debug)] 48 pub enum Error { 49 #[error("Failed converting buf to PTM ")] 50 ConvertToPtm(#[source] anyhow::Error), 51 } 52 type Result<T> = anyhow::Result<T, Error>; 53 54 #[derive(PartialEq, Eq, Copy, Clone, Debug)] 55 pub enum MemberType { 56 Request, 57 Response, 58 Error, 59 Cap, 60 } 61 62 pub trait Ptm { 63 // Get Member Type 64 fn get_member_type(&self) -> MemberType; 65 66 // Set Member Type 67 fn set_member_type(&mut self, mem: MemberType); 68 69 // Convert PTM Request to bytes to be sent to tpm 70 fn ptm_to_request(&self) -> Vec<u8>; 71 72 // Update PTM from tpm's response 73 fn update_ptm_with_response(&mut self, buf: &[u8]) -> Result<()>; 74 75 // Update tpm result 76 fn set_result_code(&mut self, res: u32); 77 78 fn get_result_code(&self) -> u32; 79 } 80 81 /* 82 * Every response for a tpm Control Command execution must hold tpm return 83 * code (PtmResult) as its first element. 84 * Based on the type of input Control Command additional data could be 85 * appended to the response. 86 */ 87 pub type PtmResult = u32; 88 89 impl Ptm for PtmResult { 90 fn ptm_to_request(&self) -> Vec<u8> { 91 Vec::new() 92 } 93 94 fn get_member_type(&self) -> MemberType { 95 MemberType::Response 96 } 97 98 fn update_ptm_with_response(&mut self, buf: &[u8]) -> Result<()> { 99 let expected_len = 4; 100 let len = buf.len(); 101 if len != expected_len { 102 return Err(Error::ConvertToPtm(anyhow!( 103 "PtmRes buffer is of incorrect length. Got {len} expected {expected_len}." 104 ))); 105 } 106 107 *self = u32::from_be_bytes(buf[..].try_into().unwrap()); 108 Ok(()) 109 } 110 111 fn set_member_type(&mut self, _mem: MemberType) {} 112 113 fn set_result_code(&mut self, res: u32) { 114 *self = res; 115 } 116 117 fn get_result_code(&self) -> u32 { 118 *self 119 } 120 } 121 122 /* GET_CAPABILITY Response */ 123 pub type PtmCap = u64; 124 impl Ptm for PtmCap { 125 fn ptm_to_request(&self) -> Vec<u8> { 126 // tpm's GetCapability call doesn't need any supporting message 127 // return an empty Buffer 128 Vec::new() 129 } 130 131 fn get_member_type(&self) -> MemberType { 132 MemberType::Cap 133 } 134 135 fn update_ptm_with_response(&mut self, buf: &[u8]) -> Result<()> { 136 let expected_len = 8; 137 let len = buf.len(); 138 if len != expected_len { 139 return Err(Error::ConvertToPtm(anyhow!( 140 "Response for GetCapability cmd is of incorrect length. Got {len} expected {expected_len}." 141 ))); 142 } 143 *self = u64::from_be_bytes(buf[..].try_into().unwrap()); 144 Ok(()) 145 } 146 147 fn set_member_type(&mut self, _mem: MemberType) {} 148 149 fn set_result_code(&mut self, _res: u32) {} 150 151 fn get_result_code(&self) -> u32 { 152 ((*self) >> 32) as u32 153 } 154 } 155 156 /* GET_TPMESTABLISHED Response */ 157 #[derive(Debug)] 158 pub struct PtmEstResp { 159 pub bit: u8, 160 } 161 162 #[derive(Debug)] 163 pub struct PtmEst { 164 member: MemberType, 165 pub resp: PtmEstResp, 166 pub result_code: PtmResult, 167 } 168 169 impl PtmEst { 170 pub fn new() -> Self { 171 Self { 172 member: MemberType::Response, 173 result_code: 0, 174 resp: PtmEstResp { bit: 0 }, 175 } 176 } 177 } 178 179 impl Default for PtmEst { 180 fn default() -> Self { 181 Self::new() 182 } 183 } 184 185 impl Ptm for PtmEst { 186 fn ptm_to_request(&self) -> Vec<u8> { 187 // tpm's GetTpmEstablished call doesn't need any supporting message 188 // return an empty Buffer 189 Vec::new() 190 } 191 192 fn get_member_type(&self) -> MemberType { 193 self.member 194 } 195 196 fn update_ptm_with_response(&mut self, buf: &[u8]) -> Result<()> { 197 let expected_len = 8; 198 let len = buf.len(); 199 if len != expected_len { 200 return Err(Error::ConvertToPtm(anyhow!( 201 "Response for GetTpmEstablished cmd is of incorrect length. Got {len} expected {expected_len}." 202 ))); 203 } 204 self.set_result_code(u32::from_be_bytes(buf[..4].try_into().unwrap())); 205 self.resp.bit = buf[4]; 206 Ok(()) 207 } 208 209 fn set_member_type(&mut self, _mem: MemberType) {} 210 211 fn set_result_code(&mut self, res: u32) { 212 self.result_code = res 213 } 214 215 fn get_result_code(&self) -> u32 { 216 self.result_code 217 } 218 } 219 220 /* INIT Response */ 221 222 #[derive(Debug)] 223 pub struct PtmInit { 224 pub member: MemberType, 225 /* request */ 226 pub init_flags: u32, 227 /* response */ 228 pub result_code: PtmResult, 229 } 230 231 impl Default for PtmInit { 232 fn default() -> Self { 233 Self::new() 234 } 235 } 236 237 impl PtmInit { 238 pub fn new() -> Self { 239 Self { 240 member: MemberType::Request, 241 init_flags: 0, 242 result_code: 0, 243 } 244 } 245 } 246 247 impl Ptm for PtmInit { 248 fn ptm_to_request(&self) -> Vec<u8> { 249 let mut buf: Vec<u8> = Vec::<u8>::new(); 250 buf.extend_from_slice(&self.init_flags.to_be_bytes()); 251 buf 252 } 253 254 fn get_member_type(&self) -> MemberType { 255 self.member 256 } 257 258 fn update_ptm_with_response(&mut self, buf: &[u8]) -> Result<()> { 259 let expected_len = 4; 260 let len = buf.len(); 261 if len != expected_len { 262 return Err(Error::ConvertToPtm(anyhow!( 263 "Response for Init cmd is of incorrect length. Got {len} expected {expected_len}." 264 ))); 265 } 266 self.set_member_type(MemberType::Response); 267 self.set_result_code(u32::from_be_bytes(buf[..].try_into().unwrap())); 268 Ok(()) 269 } 270 271 fn set_member_type(&mut self, mem: MemberType) { 272 self.member = mem 273 } 274 275 fn set_result_code(&mut self, res: u32) { 276 self.result_code = res 277 } 278 279 fn get_result_code(&self) -> u32 { 280 self.result_code 281 } 282 } 283 284 /* 285 * PTM_SET_BUFFERSIZE: Set the buffer size to be used by the tpm. 286 * A 0 on input queries for the current buffer size. Any other 287 * number will try to set the buffer size. The returned number is 288 * the buffer size that will be used, which can be larger than the 289 * requested one, if it was below the minimum, or smaller than the 290 * requested one, if it was above the maximum. 291 * 292 * SET_BUFFERSIZE Response 293 */ 294 #[derive(Debug)] 295 pub struct PtmSBSReq { 296 buffersize: u32, 297 } 298 299 #[derive(Debug)] 300 pub struct PtmSBSResp { 301 bufsize: u32, 302 minsize: u32, 303 maxsize: u32, 304 } 305 306 #[derive(Debug)] 307 pub struct PtmSetBufferSize { 308 pub mem: MemberType, 309 /* request */ 310 pub req: PtmSBSReq, 311 /* response */ 312 pub resp: PtmSBSResp, 313 pub result_code: PtmResult, 314 } 315 316 impl PtmSetBufferSize { 317 pub fn new(req_buffsize: u32) -> Self { 318 Self { 319 mem: MemberType::Request, 320 req: PtmSBSReq { 321 buffersize: req_buffsize, 322 }, 323 resp: PtmSBSResp { 324 bufsize: 0, 325 minsize: 0, 326 maxsize: 0, 327 }, 328 result_code: 0, 329 } 330 } 331 pub fn get_bufsize(&self) -> u32 { 332 self.resp.bufsize 333 } 334 } 335 336 impl Ptm for PtmSetBufferSize { 337 fn ptm_to_request(&self) -> Vec<u8> { 338 let mut buf: Vec<u8> = Vec::<u8>::new(); 339 buf.extend_from_slice(&self.req.buffersize.to_be_bytes()); 340 buf 341 } 342 343 fn get_member_type(&self) -> MemberType { 344 self.mem 345 } 346 347 fn update_ptm_with_response(&mut self, buf: &[u8]) -> Result<()> { 348 let expected_len = 16; 349 let len = buf.len(); 350 if len != expected_len { 351 return Err(Error::ConvertToPtm(anyhow!( 352 "Response for CmdSetBufferSize cmd is of incorrect length. Got {len} expected {expected_len}." 353 ))); 354 } 355 self.set_member_type(MemberType::Response); 356 self.set_result_code(u32::from_be_bytes(buf[0..4].try_into().unwrap())); 357 358 let bufsize = &buf[4..8]; 359 self.resp.bufsize = u32::from_be_bytes(bufsize.try_into().unwrap()); 360 361 let minsize = &buf[8..12]; 362 self.resp.minsize = u32::from_be_bytes(minsize.try_into().unwrap()); 363 364 let maxsize = &buf[12..16]; 365 self.resp.maxsize = u32::from_be_bytes(maxsize.try_into().unwrap()); 366 367 Ok(()) 368 } 369 370 fn set_member_type(&mut self, mem: MemberType) { 371 self.mem = mem 372 } 373 374 fn set_result_code(&mut self, res: u32) { 375 self.result_code = res 376 } 377 378 fn get_result_code(&self) -> u32 { 379 self.result_code 380 } 381 } 382 383 #[cfg(test)] 384 mod tests { 385 use super::*; 386 #[test] 387 fn test_ptmresult() -> Result<()> { 388 let buf: &[u8] = &[0, 0, 0, 1]; 389 let mut result_code: PtmResult = 0; 390 result_code.update_ptm_with_response(buf)?; 391 assert_eq!(result_code.get_result_code(), 0x1); 392 Ok(()) 393 } 394 #[test] 395 fn test_ptmcap() -> Result<()> { 396 let mut cap: PtmCap = 0x0; 397 let buf: &[u8] = &[0, 0, 0, 0xE, 0, 0, 0xFF, 0xFF]; 398 cap.update_ptm_with_response(buf)?; 399 assert_eq!(cap.get_result_code(), 0xE); 400 Ok(()) 401 } 402 #[test] 403 fn test_ptmest() -> Result<()> { 404 let mut est: PtmEst = PtmEst::new(); 405 let buf: &[u8] = &[0, 0, 0xE, 0, 0xC, 0, 1, 1]; 406 est.update_ptm_with_response(buf)?; 407 assert_eq!(est.get_result_code(), 0xE00); 408 assert_eq!(est.resp.bit, 0xC); 409 Ok(()) 410 } 411 #[test] 412 /*PtmInit Testing */ 413 fn test_ptminit() -> Result<()> { 414 let mut init: PtmInit = PtmInit::new(); 415 init.init_flags = 0x1; 416 let buf = init.ptm_to_request(); 417 assert_eq!(buf, [0x0, 0x0, 0x0, 0x1]); 418 let response_buf: &[u8] = &[0, 0, 0xE, 0]; 419 init.update_ptm_with_response(response_buf)?; 420 assert_eq!(init.get_result_code(), 0xE00); 421 Ok(()) 422 } 423 #[test] 424 /* PtmSetBufferSize Testing */ 425 fn test_ptmsetbuffersize() -> Result<()> { 426 let mut psbs: PtmSetBufferSize = PtmSetBufferSize::new(1024); 427 // Member type should be Request after initialization 428 assert_eq!(psbs.get_member_type(), MemberType::Request); 429 let buf: &[u8] = &[ 430 0, 0x12, 0x34, 0x56, 0, 0, 0, 0xA, 0, 0, 0, 0xB, 0, 0, 0, 0xC, 431 ]; 432 psbs.update_ptm_with_response(buf)?; 433 assert_eq!(psbs.get_member_type(), MemberType::Response); 434 assert_eq!(psbs.get_result_code(), 0x123456); 435 assert_eq!(psbs.resp.bufsize, 0xA); 436 assert_eq!(psbs.resp.minsize, 0xB); 437 assert_eq!(psbs.resp.maxsize, 0xC); 438 Ok(()) 439 } 440 } 441