1pub(crate) mod ioctl;
9use ioctl::*;
10
11pub(crate) mod types;
12use types::*;
13
14use crate::{
15 certs::{csv::Certificate, Signer, Usage, Verifiable},
16 crypto::{sig::ecdsa, sm, PrivateKey, PublicKey, Signature},
17 util::*,
18 Version,
19};
20
21use bitflags::bitflags;
22use serde::{Deserialize, Serialize};
23use serde_big_array::BigArray;
24use std::{
25 convert::*,
26 io::{Read, Result, Write},
27 mem::MaybeUninit,
28 os::unix::io::AsRawFd,
29};
30
31pub struct New;
33
34pub struct Started(Handle);
36
37pub struct Measured(Handle, Measurement);
39
40pub struct Launcher<T, U: AsRawFd, V: AsRawFd> {
42 state: T,
43 vm_fd: U,
44 csv: V,
45}
46
47impl<T, U: AsRawFd, V: AsRawFd> Launcher<T, U, V> {
48 pub fn as_mut_vmfd(&mut self) -> &mut U {
50 &mut self.vm_fd
51 }
52}
53
54impl<U: AsRawFd, V: AsRawFd> Launcher<New, U, V> {
55 pub fn new(kvm: U, csv: V) -> Result<Self> {
57 let mut launcher = Launcher {
58 vm_fd: kvm,
59 csv,
60 state: New,
61 };
62
63 let mut cmd = Command::from(&mut launcher.csv, &Init);
64 INIT.ioctl(&mut launcher.vm_fd, &mut cmd)
65 .map_err(|e| cmd.encapsulate(e))?;
66
67 Ok(launcher)
68 }
69
70 pub fn new_es(kvm: U, csv: V) -> Result<Self> {
72 let mut launcher = Launcher {
73 vm_fd: kvm,
74 csv,
75 state: New,
76 };
77
78 let mut cmd = Command::from(&mut launcher.csv, &EsInit);
79 ES_INIT
80 .ioctl(&mut launcher.vm_fd, &mut cmd)
81 .map_err(|e| cmd.encapsulate(e))?;
82
83 Ok(launcher)
84 }
85
86 pub fn start(mut self, start: Start) -> Result<Launcher<Started, U, V>> {
88 let mut launch_start = LaunchStart::new(&start.policy, &start.cert, &start.session);
89 let mut cmd = Command::from_mut(&mut self.csv, &mut launch_start);
90 LAUNCH_START
91 .ioctl(&mut self.vm_fd, &mut cmd)
92 .map_err(|e| cmd.encapsulate(e))?;
93
94 let next = Launcher {
95 state: Started(launch_start.into()),
96 vm_fd: self.vm_fd,
97 csv: self.csv,
98 };
99
100 Ok(next)
101 }
102
103 pub fn start_raw(
105 mut self,
106 policy: &Policy,
107 cert: &Certificate,
108 session: &Session,
109 ) -> Result<Launcher<Started, U, V>> {
110 let mut launch_start = LaunchStart::new(policy, cert, session);
111 let mut cmd = Command::from_mut(&mut self.csv, &mut launch_start);
112 LAUNCH_START
113 .ioctl(&mut self.vm_fd, &mut cmd)
114 .map_err(|e| cmd.encapsulate(e))?;
115
116 let next = Launcher {
117 state: Started(launch_start.into()),
118 vm_fd: self.vm_fd,
119 csv: self.csv,
120 };
121
122 Ok(next)
123 }
124
125 pub fn start_with_policy_only(mut self, policy: Policy) -> Result<Launcher<Started, U, V>> {
127 let mut launch_start = LaunchStart::with_policy_only(&policy);
128 let mut cmd = Command::from_mut(&mut self.csv, &mut launch_start);
129 LAUNCH_START
130 .ioctl(&mut self.vm_fd, &mut cmd)
131 .map_err(|e| cmd.encapsulate(e))?;
132
133 let next = Launcher {
134 state: Started(launch_start.into()),
135 vm_fd: self.vm_fd,
136 csv: self.csv,
137 };
138
139 Ok(next)
140 }
141}
142
143impl<U: AsRawFd, V: AsRawFd> Launcher<Started, U, V> {
144 pub fn update_data(&mut self, data: &[u8]) -> Result<()> {
146 let launch_update_data = LaunchUpdateData::new(data);
147 let mut cmd = Command::from(&mut self.csv, &launch_update_data);
148
149 KvmEncRegion::new(data).register(&mut self.vm_fd)?;
150
151 LAUNCH_UPDATE_DATA
152 .ioctl(&mut self.vm_fd, &mut cmd)
153 .map_err(|e| cmd.encapsulate(e))?;
154
155 Ok(())
156 }
157
158 pub fn register_kvm_enc_region(&mut self, data: &[u8]) -> Result<()> {
161 KvmEncRegion::new(data).register(&mut self.vm_fd)?;
162 Ok(())
163 }
164
165 pub fn update_data_without_registration(&mut self, data: &[u8]) -> Result<()> {
167 let launch_update_data = LaunchUpdateData::new(data);
168 let mut cmd = Command::from(&mut self.csv, &launch_update_data);
169
170 LAUNCH_UPDATE_DATA
171 .ioctl(&mut self.vm_fd, &mut cmd)
172 .map_err(|e| cmd.encapsulate(e))?;
173
174 Ok(())
175 }
176
177 pub fn update_vmsa(&mut self) -> Result<()> {
179 let launch_update_vmsa = LaunchUpdateVmsa::new();
180 let mut cmd = Command::from(&mut self.csv, &launch_update_vmsa);
181
182 LAUNCH_UPDATE_VMSA
183 .ioctl(&mut self.vm_fd, &mut cmd)
184 .map_err(|e| cmd.encapsulate(e))?;
185
186 Ok(())
187 }
188
189 pub fn measure(mut self) -> Result<Launcher<Measured, U, V>> {
191 let mut measurement = MaybeUninit::uninit();
192 let mut launch_measure = LaunchMeasure::new(&mut measurement);
193 let mut cmd = Command::from_mut(&mut self.csv, &mut launch_measure);
194 LAUNCH_MEASUREMENT
195 .ioctl(&mut self.vm_fd, &mut cmd)
196 .map_err(|e| cmd.encapsulate(e))?;
197
198 let next = Launcher {
199 state: Measured(self.state.0, unsafe { measurement.assume_init() }),
200 vm_fd: self.vm_fd,
201 csv: self.csv,
202 };
203
204 Ok(next)
205 }
206}
207
208impl<U: AsRawFd, V: AsRawFd> Launcher<Measured, U, V> {
209 pub fn measurement(&self) -> Measurement {
211 self.state.1
212 }
213
214 pub fn get_attestation_report(&mut self, mnonce: [u8; 16]) -> Result<Box<AttestationReport>> {
216 let mut ar = MaybeUninit::uninit();
217 let mut attestation = Attestation::new(&mut ar, mnonce);
218 let mut cmd = Command::from_mut(&mut self.csv, &mut attestation);
219 ATTESTATION
220 .ioctl(&mut self.vm_fd, &mut cmd)
221 .map_err(|e| cmd.encapsulate(e))?;
222
223 Ok(Box::new(unsafe { ar.assume_init() }))
224 }
225
226 pub fn inject(&mut self, secret: &Secret, guest: usize) -> Result<()> {
232 let launch_secret = LaunchSecret::new(&secret.header, guest, &secret.ciphertext[..]);
233 let mut cmd = Command::from(&mut self.csv, &launch_secret);
234 LAUNCH_SECRET
235 .ioctl(&mut self.vm_fd, &mut cmd)
236 .map_err(|e| cmd.encapsulate(e))?;
237 Ok(())
238 }
239
240 pub fn finish(mut self) -> Result<Handle> {
242 let mut cmd = Command::from(&mut self.csv, &LaunchFinish);
243 LAUNCH_FINISH
244 .ioctl(&mut self.vm_fd, &mut cmd)
245 .map_err(|e| cmd.encapsulate(e))?;
246 Ok(self.state.0)
247 }
248}
249
250bitflags! {
251 #[derive(Default, Deserialize, Serialize)]
253 pub struct PolicyFlags: u16 {
254 const NO_DEBUG = 0b00000001u16.to_le();
256
257 const NO_KEY_SHARING = 0b00000010u16.to_le();
259
260 const ENCRYPTED_STATE = 0b00000100u16.to_le();
262
263 const NO_SEND = 0b00001000u16.to_le();
265
266 const DOMAIN = 0b00010000u16.to_le();
269
270 const CSV = 0b00100000u16.to_le();
273 }
274}
275
276#[repr(C)]
279#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
280pub struct Policy {
281 pub flags: PolicyFlags,
283
284 pub minfw: Version,
286}
287
288impl From<u32> for Policy {
290 fn from(p: u32) -> Self {
291 let flags = p as u16;
292 let flags = PolicyFlags::from_bits_truncate(flags);
293
294 let p = p >> 16;
295 let p = p as u16;
296 let minfw = Version::from(p);
297
298 Self { flags, minfw }
299 }
300}
301
302#[repr(C)]
304#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
305pub struct SessionBody {
306 pub nonce: [u8; 16],
309
310 pub wrap_tk: [u8; 32],
314
315 pub wrap_iv: [u8; 16],
317
318 pub wrap_mac: [u8; 32],
321
322 pub session_mac: [u8; 32],
324
325 pub key_id: [u8; 16],
327
328 #[serde(with = "BigArray")]
330 pub rnd_pub_key_data: [u8; 148],
331
332 #[serde(with = "BigArray")]
334 pub ms_enc: [u8; 256],
335
336 pub vm_digest: [u8; 32],
338
339 pub pubkey_digest: [u8; 32],
341
342 pub vm_id: [u8; 16],
344
345 pub vm_version: [u8; 16],
347
348 #[serde(with = "BigArray")]
350 pub user_data: [u8; 64],
351}
352
353#[repr(C)]
354#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
355pub struct SessionSig {
356 pub r: [u8; 32],
358 pub s: [u8; 32],
360}
361
362impl From<ecdsa::Signature> for SessionSig {
363 #[inline]
364 fn from(value: ecdsa::Signature) -> Self {
365 let mut r = [0u8; 32];
366 let mut s = [0u8; 32];
367 for (i, b) in value.r.iter().take(32).cloned().enumerate() {
368 r[i] = b;
369 }
370 for (i, b) in value.s.iter().take(32).cloned().enumerate() {
371 s[i] = b;
372 }
373 SessionSig { r, s }
374 }
375}
376
377impl From<SessionSig> for ecdsa::Signature {
378 #[inline]
379 fn from(value: SessionSig) -> Self {
380 let mut r = [0u8; 72];
381 let mut s = [0u8; 72];
382 for (i, b) in value.r.iter().cloned().enumerate() {
383 r[i] = b;
384 }
385 for (i, b) in value.s.iter().cloned().enumerate() {
386 s[i] = b;
387 }
388 ecdsa::Signature { r, s }
389 }
390}
391
392#[repr(C)]
395#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
396pub struct Session {
397 pub body: SessionBody,
400 pub sig: SessionSig,
401}
402
403impl Signer<Session> for PrivateKey<Usage> {
404 type Output = ();
405
406 fn sign(&self, target: &mut Session, uid: String) -> Result<()> {
407 let slot = &mut target.sig;
408
409 let mut msg: Vec<u8> = Vec::new();
410 msg.save(&target.body)?;
411
412 let sig = sm::SM2::sign(self.key, uid.as_bytes(), &msg)?;
413
414 let ecdsa_sig = ecdsa::Signature::try_from(&sig[..])?;
415
416 *slot = SessionSig::from(ecdsa_sig);
417 Ok(())
418 }
419}
420
421impl TryFrom<&Session> for Signature {
422 type Error = std::io::Error;
423
424 #[inline]
425 fn try_from(value: &Session) -> Result<Self> {
426 let sig = ecdsa::Signature::from(value.sig);
427
428 let sig = Vec::try_from(&sig)?;
429 Ok(Self {
430 sig,
431 id: None,
432 usage: Usage::PDH,
433 algo: None,
434 })
435 }
436}
437
438impl codicon::Encoder<crate::Body> for Session {
439 type Error = std::io::Error;
440
441 fn encode(&self, mut writer: impl Write, _: crate::Body) -> Result<()> {
442 writer.save(&self.body)
443 }
444}
445
446impl Verifiable for (&Certificate, &Session) {
447 type Output = ();
448
449 fn verify(self) -> Result<()> {
450 let key: PublicKey = self.0.try_into()?;
451 let sig: Signature = self.1.try_into()?;
452 key.verify(
453 self.1,
454 &self.0.body.data.user_id[..self.0.body.data.uid_size as usize],
455 &sig,
456 )
457 }
458}
459
460#[repr(C)]
462#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
463pub struct Start {
464 pub policy: Policy,
466
467 pub cert: Certificate,
469
470 pub session: Session,
472}
473
474impl codicon::Decoder<()> for Start {
475 type Error = std::io::Error;
476
477 fn decode(mut reader: impl Read, _: ()) -> std::io::Result<Self> {
478 reader.load()
479 }
480}
481
482impl codicon::Encoder<()> for Start {
483 type Error = std::io::Error;
484
485 fn encode(&self, mut writer: impl Write, _: ()) -> std::io::Result<()> {
486 writer.save(self)
487 }
488}
489
490bitflags! {
491 #[derive(Default, Deserialize, Serialize)]
493 pub struct HeaderFlags: u32 {
494 const COMPRESSED = 0b00000001u32.to_le();
497 }
498}
499
500#[repr(C)]
503#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
504pub struct Header {
505 pub flags: HeaderFlags,
508
509 pub iv: [u8; 16],
511
512 pub mac: [u8; 32],
514}
515
516#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
519pub struct Secret {
520 pub header: Header,
522
523 pub ciphertext: Vec<u8>,
525}
526
527#[repr(C)]
529#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
530pub struct Measurement {
531 pub measure: [u8; 32],
533
534 pub mnonce: [u8; 16],
536}
537
538#[repr(C)]
539#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
540pub struct AttestationReport {
541 pub mnonce: [u8; 16],
543
544 pub digest: [u8; 32],
545
546 pub policy: Policy,
548
549 pub sig_usage: [u8; 4],
551
552 pub sig_algo: [u8; 4],
554
555 reserved: [u8; 4],
557
558 pub sig1: [[u8; 16]; 9],
559}