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