@@ -13,20 +13,21 @@ use crate::{
1313 io:: { Read , Write , DEFAULT_IO_DRIVER } ,
1414 serial:: SerialPort ,
1515} ;
16+ use aes:: { cipher:: BlockDecrypt , Aes256 } ;
17+ use aes_gcm:: KeyInit ;
1618use alloc:: { string:: ToString , vec, vec:: Vec } ;
1719use base64:: { prelude:: * , Engine } ;
1820use cocoon_tpm_crypto:: {
19- ecc,
21+ ecc:: { curve :: Curve , ecdh :: ecdh_c_1e_1s_cdh_party_v_key_gen , EccKey } ,
2022 rng:: { self , HashDrbg , RngCore as _, X86RdSeedRng } ,
2123 CryptoError , EmptyCryptoIoSlices ,
2224} ;
23- use cocoon_tpm_tpm2_interface:: {
24- self as tpm2_interface, Tpm2bEccParameter , TpmEccCurve , TpmiAlgHash , TpmsEccPoint ,
25- } ;
25+ use cocoon_tpm_tpm2_interface:: { self as tpm2_interface, TpmEccCurve , TpmiAlgHash , TpmsEccPoint } ;
2626use cocoon_tpm_utils_common:: {
2727 alloc:: try_alloc_zeroizing_vec,
2828 io_slices:: { self , IoSlicesIterCommon as _} ,
2929} ;
30+ use core:: cmp:: min;
3031use kbs_types:: Tee ;
3132use libaproxy:: * ;
3233use serde:: Serialize ;
@@ -35,12 +36,12 @@ use zerocopy::{FromBytes, IntoBytes};
3536
3637/// The attestation driver that communicates with the proxy via some communication channel (serial
3738/// port, virtio-vsock, etc...).
38- #[ derive ( Debug ) ]
39+ #[ allow ( missing_debug_implementations ) ]
3940pub struct AttestationDriver < ' a > {
4041 sp : SerialPort < ' a > ,
4142 tee : Tee ,
42- pub_key : TpmsEccPoint < ' static > ,
43- _priv_key : Tpm2bEccParameter < ' static > ,
43+ ecc : EccKey ,
44+ curve : Curve ,
4445}
4546
4647impl TryFrom < Tee > for AttestationDriver < ' _ > {
@@ -57,13 +58,14 @@ impl TryFrom<Tee> for AttestationDriver<'_> {
5758 _ => return Err ( AttestationError :: UnsupportedTee . into ( ) ) ,
5859 }
5960
60- let key = sc_key_generate ( TpmEccCurve :: NistP384 ) . map_err ( AttestationError :: KeyGen ) ?;
61+ let curve = Curve :: new ( TpmEccCurve :: NistP384 ) . map_err ( AttestationError :: Crypto ) ?;
62+ let ecc = sc_key_generate ( & curve) . map_err ( AttestationError :: Crypto ) ?;
6163
6264 Ok ( Self {
6365 sp,
6466 tee,
65- pub_key : key . 0 ,
66- _priv_key : key . 1 ,
67+ ecc ,
68+ curve ,
6769 } )
6870 }
6971}
@@ -73,7 +75,8 @@ impl AttestationDriver<'_> {
7375 pub fn attest ( & mut self ) -> Result < Vec < u8 > , SvsmError > {
7476 let negotiation = self . negotiation ( ) ?;
7577
76- Ok ( self . attestation ( negotiation) ?)
78+ self . attestation ( negotiation)
79+ . map_err ( SvsmError :: TeeAttestation )
7780 }
7881
7982 /// Send a negotiation request to the proxy. Proxy should reply with Negotiation parameters
@@ -95,15 +98,19 @@ impl AttestationDriver<'_> {
9598 /// containing the status (success/fail) and an optional secret returned from the server upon
9699 /// successful attestation.
97100 fn attestation ( & mut self , n : NegotiationResponse ) -> Result < Vec < u8 > , AttestationError > {
98- let evidence = evidence ( & self . tee , hash ( n, & self . pub_key ) ?) ?;
101+ let pub_key = self
102+ . ecc
103+ . pub_key ( )
104+ . to_tpms_ecc_point ( & self . curve . curve_ops ( ) . map_err ( AttestationError :: Crypto ) ?)
105+ . map_err ( AttestationError :: Crypto ) ?;
106+
107+ let evidence = evidence ( & self . tee , hash ( n, & pub_key) ?) ?;
99108
100109 let req = AttestationRequest {
101110 evidence : BASE64_URL_SAFE . encode ( evidence) ,
102- key : AttestationKey :: EC {
103- crv : "EC384" . to_string ( ) ,
104- x_b64url : BASE64_URL_SAFE . encode ( & * self . pub_key . x . buffer ) ,
105- y_b64url : BASE64_URL_SAFE . encode ( & * self . pub_key . y . buffer ) ,
106- } ,
111+ key : ( TpmEccCurve :: NistP384 , & pub_key)
112+ . try_into ( )
113+ . map_err ( |_| AttestationError :: AttestationDeserialize ) ?,
107114 } ;
108115
109116 self . write ( req) ?;
@@ -112,7 +119,49 @@ impl AttestationDriver<'_> {
112119 let response: AttestationResponse = serde_json:: from_slice ( & payload)
113120 . map_err ( |_| AttestationError :: AttestationDeserialize ) ?;
114121
115- todo ! ( ) ;
122+ if !response. success {
123+ return Err ( AttestationError :: Failed ) ;
124+ }
125+
126+ let Some ( ak) = response. pub_key else {
127+ return Err ( AttestationError :: PublicKeyMissing ) ?;
128+ } ;
129+
130+ let pub_key: TpmsEccPoint < ' static > = ak. try_into ( ) . map_err ( AttestationError :: Crypto ) ?;
131+
132+ let Some ( ciphertext) = response. secret else {
133+ return Err ( AttestationError :: SecretMissing ) ;
134+ } ;
135+
136+ self . decrypt ( ciphertext, pub_key)
137+ }
138+
139+ /// Decrypt a secret from the attestation server with the TEE private key.
140+ fn decrypt (
141+ & self ,
142+ ciphertext : Vec < u8 > ,
143+ pub_key : TpmsEccPoint < ' static > ,
144+ ) -> Result < Vec < u8 > , AttestationError > {
145+ let shared_secret =
146+ ecdh_c_1e_1s_cdh_party_v_key_gen ( TpmiAlgHash :: Sha256 , "" , & self . ecc , & pub_key)
147+ . map_err ( AttestationError :: Crypto ) ?;
148+
149+ let aes = Aes256 :: new_from_slice ( & shared_secret[ ..] )
150+ . map_err ( |_| AttestationError :: AesGenerate ) ?;
151+ // Decrypt each 16-byte block of the ciphertext with the symmetric key.
152+ let mut ptr = 0 ;
153+ let len = ciphertext. len ( ) ;
154+ let mut vec: Vec < u8 > = Vec :: new ( ) ;
155+ while ptr < len {
156+ let remain = min ( 16 , len - ptr) ;
157+ let mut arr: [ u8 ; 16 ] = [ 0u8 ; 16 ] ;
158+ arr[ ..remain] . copy_from_slice ( & ciphertext[ ptr..ptr + remain] ) ;
159+ aes. decrypt_block ( ( & mut arr) . into ( ) ) ;
160+ vec. append ( & mut arr. to_vec ( ) ) ;
161+ ptr += remain;
162+ }
163+
164+ Ok ( vec)
116165 }
117166
118167 /// Read attestation data from the serial port.
@@ -154,8 +203,12 @@ impl AttestationDriver<'_> {
154203/// Possible errors when attesting TEE evidence.
155204#[ derive( Clone , Copy , Debug ) ]
156205pub enum AttestationError {
206+ /// Error generating AES key.
207+ AesGenerate ,
157208 /// Error deserializing the attestation response from JSON bytes.
158209 AttestationDeserialize ,
210+ /// Guest has failed attestation.
211+ Failed ,
159212 /// Error deserializing the negotiation response from JSON bytes.
160213 NegotiationDeserialize ,
161214 /// Error serializing the negotiation request to JSON bytes.
@@ -164,10 +217,16 @@ pub enum AttestationError {
164217 ProxyRead ,
165218 /// Error writing over the attestation proxy transport channel.
166219 ProxyWrite ,
220+ /// Attestation successful, but no public key found.
221+ PublicKeyMissing ,
167222 /// Unsupported TEE architecture.
168223 UnsupportedTee ,
169224 /// Unable to generate secure channel key.
170- KeyGen ( CryptoError ) ,
225+ Crypto ( CryptoError ) ,
226+ /// Attestation successful, but unable to decrypt secret.
227+ SecretDecrypt ,
228+ /// Attestation successful, but no secret found.
229+ SecretMissing ,
171230 /// Unable to fetch SEV-SNP attestation report.
172231 SnpGetReport ,
173232}
@@ -180,9 +239,7 @@ impl From<AttestationError> for SvsmError {
180239
181240/// Generate a key used to establish a secure channel between the confidential guest and
182241/// attestation server.
183- fn sc_key_generate (
184- curve_id : TpmEccCurve ,
185- ) -> Result < ( TpmsEccPoint < ' static > , Tpm2bEccParameter < ' static > ) , CryptoError > {
242+ fn sc_key_generate ( curve : & Curve ) -> Result < EccKey , CryptoError > {
186243 let mut rng = {
187244 let mut rdseed = X86RdSeedRng :: instantiate ( ) . map_err ( |_| CryptoError :: RngFailure ) ?;
188245 let mut hash_drbg_entropy =
@@ -202,15 +259,9 @@ fn sc_key_generate(
202259 )
203260 } ?;
204261
205- let curve = ecc:: curve:: Curve :: new ( curve_id) ?;
206262 let curve_ops = curve. curve_ops ( ) ?;
207- let ecc_key = ecc:: EccKey :: generate ( & curve_ops, & mut rng, None ) ?;
208-
209- let ( pub_key, priv_key) = ecc_key. into_tpms ( & curve_ops) ?;
210-
211- let priv_key = priv_key. ok_or ( CryptoError :: Internal ) ?;
212263
213- Ok ( ( pub_key , priv_key ) )
264+ EccKey :: generate ( & curve_ops , & mut rng , None )
214265}
215266
216267/// Hash negotiation parameters and fetch TEE evidence.
0 commit comments