1mod key;
10
11use crate::certs::{csv, Signer, Usage};
12use crate::crypto::PrivateKey;
13
14use super::*;
15
16use std::io::{Error, Result};
17
18use openssl::*;
19
20pub struct Initialized;
22
23pub struct Measuring(hash::Hasher);
26
27pub struct Verified(api::launch::Measurement);
29
30pub struct Session<T> {
34 policy: api::launch::Policy,
35
36 pub tek: key::Key,
38
39 pub tik: key::Key,
41
42 data: T,
43}
44
45impl api::launch::Policy {
46 fn bytes(self) -> [u8; 4] {
47 unsafe { std::mem::transmute(self) }
48 }
49}
50
51impl std::convert::TryFrom<api::launch::Policy> for Session<Initialized> {
52 type Error = std::io::Error;
53
54 fn try_from(value: api::launch::Policy) -> Result<Self> {
55 Ok(Self {
56 tek: key::Key::random(16)?,
57 tik: key::Key::random(16)?,
58 data: Initialized,
59 policy: value,
60 })
61 }
62}
63
64impl Session<Initialized> {
65 fn session(
66 &self,
67 nonce: [u8; 16],
68 iv: [u8; 16],
69 z: key::Key,
70 pdh_host: &csv::Certificate,
71 prv: PrivateKey<Usage>,
72 ) -> Result<api::launch::Session> {
73 let master = z.derive(32, &nonce, "csv-master-secret")?;
74 let kek = master.derive(32, &[], "csv-kek")?;
75 let kik = master.derive(32, &[], "csv-kik")?;
76 let uid = String::from("GUEST_USER_ID");
77
78 let mut crypter = symm::Crypter::new(
79 symm::Cipher::sm4_ctr(),
80 symm::Mode::Encrypt,
81 &kek[..16],
83 Some(&iv),
84 )?;
85
86 let mut wrap = [0u8; 32];
87 let mut off = 0;
88 off += crypter.update(&self.tek, &mut wrap[off..])?;
89 off += crypter.update(&self.tik, &mut wrap[off..])?;
90 off += crypter.finalize(&mut wrap[off..])?;
91 assert_eq!(off, wrap.len());
92
93 let mut concatenated_iv_wrap = Vec::new();
94 concatenated_iv_wrap.extend_from_slice(&iv);
95 concatenated_iv_wrap.extend_from_slice(&wrap);
96
97 let mut ms_enc = pdh_host.encrypt(master.get_ref())?;
98 ms_enc.resize(256, 0);
99
100 let wmac = kik.mac(&concatenated_iv_wrap)?;
101
102 let mut session_data_needed_mac = Vec::new();
103 session_data_needed_mac.extend_from_slice(&self.policy.bytes());
104 session_data_needed_mac.extend_from_slice(&ms_enc);
105 session_data_needed_mac.resize(420, 0);
107 let session_mac = self.tik.mac(&session_data_needed_mac)?;
108
109 let body: api::launch::SessionBody = api::launch::SessionBody {
110 session_mac,
111 wrap_mac: wmac,
112 wrap_tk: wrap,
113 wrap_iv: iv,
114 nonce,
115 key_id: [0u8; 16],
116 rnd_pub_key_data: [0u8; 148],
117 ms_enc: ms_enc.try_into().unwrap(),
118 vm_digest: [0u8; 32],
119 pubkey_digest: [0u8; 32],
120 vm_id: [0u8; 16],
121 vm_version: [0u8; 16],
122 user_data: [0u8; 64],
123 };
124
125 let mut session = api::launch::Session {
126 body,
127 sig: api::launch::SessionSig {
128 r: [0u8; 32],
129 s: [0u8; 32],
130 },
131 };
132
133 prv.sign(&mut session, uid)?;
134 Ok(session)
135 }
136
137 pub fn start(&self, chain: certs::Chain) -> Result<api::launch::Start> {
139 use certs::*;
140
141 let pdh: &csv::Certificate = chain.verify()?;
142 let uid = String::from("GUEST_USER_ID");
143 let (crt, prv) = csv::Certificate::generate(Usage::PDH, Some(uid))?;
144 let mut share_key = [0u8; 16];
146 rand::rand_bytes(&mut share_key)?;
147 let z = key::Key::new(share_key.to_vec());
148
149 let mut nonce = [0u8; 16];
150 let mut iv = [0u8; 16];
151 rand::rand_bytes(&mut nonce)?;
152 rand::rand_bytes(&mut iv)?;
153
154 let session = self.session(nonce, iv, z, pdh, prv)?;
155
156 (&crt, &session).verify()?;
157
158 Ok(api::launch::Start {
159 policy: self.policy,
160 cert: crt,
161 session,
162 })
163 }
164
165 pub fn start_pdh(&self, pdh: certs::csv::Certificate) -> Result<api::launch::Start> {
168 use certs::*;
169
170 let uid = String::from("GUEST_USER_ID");
171 let (crt, prv) = csv::Certificate::generate(Usage::PDH, Some(uid.clone()))?;
172
173 let mut share_key = [0u8; 16];
175 rand::rand_bytes(&mut share_key)?;
176 let z = key::Key::new(share_key.to_vec());
177
178 let mut nonce = [0u8; 16];
179 let mut iv = [0u8; 16];
180 rand::rand_bytes(&mut nonce)?;
181 rand::rand_bytes(&mut iv)?;
182
183 let session = self.session(nonce, iv, z, &pdh, prv)?;
184
185 Ok(api::launch::Start {
186 policy: self.policy,
187 cert: crt,
188 session,
189 })
190 }
191
192 pub fn measure(self) -> Result<Session<Measuring>> {
197 Ok(Session {
198 policy: self.policy,
199 tek: self.tek,
200 tik: self.tik,
201 data: Measuring(hash::Hasher::new(hash::MessageDigest::sm3())?),
202 })
203 }
204
205 pub fn verify(
207 self,
208 _digest: &[u8],
209 _build: Build,
210 msr: api::launch::Measurement,
211 ) -> Result<Session<Verified>> {
212 Ok(Session {
227 policy: self.policy,
228 tek: self.tek,
229 tik: self.tik,
230 data: Verified(msr),
231 })
232 }
233
234 pub unsafe fn mock_verify(self, msr: api::launch::Measurement) -> Result<Session<Verified>> {
240 Ok(Session {
241 policy: self.policy,
242 tek: self.tek,
243 tik: self.tik,
244 data: Verified(msr),
245 })
246 }
247}
248
249impl Session<Measuring> {
250 pub fn update_data(&mut self, data: &[u8]) -> std::io::Result<()> {
255 Ok(self.data.0.update(data)?)
256 }
257
258 pub fn verify(
260 mut self,
261 build: Build,
262 msr: api::launch::Measurement,
263 ) -> Result<Session<Verified>> {
264 let digest = self.data.0.finish()?;
265 let session = Session {
266 policy: self.policy,
267 tek: self.tek,
268 tik: self.tik,
269 data: Initialized,
270 };
271
272 session.verify(&digest, build, msr)
273 }
274
275 pub fn verify_with_digest(
278 self,
279 build: Build,
280 msr: api::launch::Measurement,
281 digest: &[u8],
282 ) -> Result<Session<Verified>> {
283 let session = Session {
284 policy: self.policy,
285 tek: self.tek,
286 tik: self.tik,
287 data: Initialized,
288 };
289
290 session.verify(digest, build, msr)
291 }
292}
293
294impl Session<Verified> {
295 pub fn secret(
297 &self,
298 flags: api::launch::HeaderFlags,
299 data: &[u8],
300 ) -> Result<api::launch::Secret> {
301 let mut iv = [0u8; 16];
302 rand::rand_bytes(&mut iv)?;
303
304 let ciphertext = symm::encrypt(symm::Cipher::sm4_ctr(), &self.tek, Some(&iv), data)?;
305
306 let key = pkey::PKey::hmac(&self.tik)?;
307 let mut sig = sign::Signer::new(hash::MessageDigest::sm3(), &key)?;
308
309 sig.update(&[0x01u8])?;
310 sig.update(&unsafe { std::mem::transmute::<api::launch::HeaderFlags, [u8; 4]>(flags) })?;
311 sig.update(&iv)?;
312 sig.update(&(data.len() as u32).to_le_bytes())?;
313 sig.update(&(ciphertext.len() as u32).to_le_bytes())?;
314 sig.update(&ciphertext)?;
315 sig.update(&self.data.0.measure)?;
316
317 let mut mac = [0u8; 32];
318 sig.sign(&mut mac)?;
319
320 Ok(api::launch::Secret {
321 header: api::launch::Header { flags, iv, mac },
322 ciphertext,
323 })
324 }
325}
326
327#[cfg(test)]
328mod initialized {
329 use super::*;
330 use crate::{session::Session, Build, Version};
331
332 #[test]
380 fn verify() {
381 let digest = [
382 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f,
383 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b,
384 0x78, 0x52, 0xb8, 0x55,
385 ];
386 let measurement = api::launch::Measurement {
388 measure: [
389 0x6f, 0xaa, 0xb2, 0xda, 0xae, 0x38, 0x9b, 0xcd, 0x34, 0x05, 0xa0, 0x5d, 0x6c, 0xaf,
390 0xe3, 0x3c, 0x04, 0x14, 0xf7, 0xbe, 0xdd, 0x0b, 0xae, 0x19, 0xba, 0x5f, 0x38, 0xb7,
391 0xfd, 0x16, 0x64, 0xea,
392 ],
393 mnonce: [
394 0x4f, 0xbe, 0x0b, 0xed, 0xba, 0xd6, 0xc8, 0x6a, 0xe8, 0xf6, 0x89, 0x71, 0xd1, 0x03,
395 0xe5, 0x54,
396 ],
397 };
398
399 let policy = api::launch::Policy {
400 flags: api::launch::PolicyFlags::default(),
401 minfw: Default::default(),
402 };
403
404 let tek = key::Key::new(vec![0u8; 16]);
405 let tik = key::Key::new(vec![
406 0x66, 0x32, 0x0d, 0xb7, 0x31, 0x58, 0xa3, 0x5a, 0x25, 0x5d, 0x05, 0x17, 0x58, 0xe9,
407 0x5e, 0xd4,
408 ]);
409
410 let session = Session {
411 policy,
412 tek,
413 tik,
414 data: Initialized,
415 };
416 let build = Build {
417 version: Version {
418 major: 0x00,
419 minor: 0x12,
420 },
421 build: 0x0f,
422 };
423
424 session.verify(&digest, build, measurement).unwrap();
425 }
426}