@@ -5,6 +5,7 @@ use super::operation_client::OperationClient;
55use crate :: auth:: Authentication ;
66use crate :: error:: { ClientErrorKind , Error , Result } ;
77use log:: { debug, warn} ;
8+ use parsec_interface:: operations:: attest_key:: { Operation as AttestKey , Result as AttestKeyResult } ;
89use parsec_interface:: operations:: can_do_crypto:: { CheckType , Operation as CanDoCrypto } ;
910use parsec_interface:: operations:: delete_client:: Operation as DeleteClient ;
1011use parsec_interface:: operations:: list_authenticators:: {
@@ -15,6 +16,9 @@ use parsec_interface::operations::list_keys::{KeyInfo, Operation as ListKeys};
1516use parsec_interface:: operations:: list_opcodes:: Operation as ListOpcodes ;
1617use parsec_interface:: operations:: list_providers:: { Operation as ListProviders , ProviderInfo } ;
1718use parsec_interface:: operations:: ping:: Operation as Ping ;
19+ use parsec_interface:: operations:: prepare_key_attestation:: {
20+ Operation as PrepareKeyAttestation , Result as PrepareKeyAttestationResult ,
21+ } ;
1822use parsec_interface:: operations:: psa_aead_decrypt:: Operation as PsaAeadDecrypt ;
1923use parsec_interface:: operations:: psa_aead_encrypt:: Operation as PsaAeadEncrypt ;
2024use parsec_interface:: operations:: psa_algorithm:: {
@@ -1309,12 +1313,109 @@ impl BasicClient {
13091313 Ok ( ( ) )
13101314 }
13111315
1316+ /// **[Cryptographic Operation]** Get data required to prepare an
1317+ /// ActivateCredential key attestation.
1318+ ///
1319+ /// Retrieve the binary blobs required by a third party to perform a
1320+ /// MakeCredential operation, in preparation for a key attestation using
1321+ /// ActivateCredential.
1322+ ///
1323+ /// **This key attestation method is TPM-specific**
1324+ pub fn prepare_activate_credential (
1325+ & self ,
1326+ attested_key_name : String ,
1327+ attesting_key_name : Option < String > ,
1328+ ) -> Result < PrepareActivateCredential > {
1329+ self . can_use_provider ( ProviderId :: Tpm ) ?;
1330+
1331+ let op = PrepareKeyAttestation :: ActivateCredential {
1332+ attested_key_name,
1333+ attesting_key_name,
1334+ } ;
1335+
1336+ let res = self . op_client . process_operation (
1337+ NativeOperation :: PrepareKeyAttestation ( op) ,
1338+ ProviderId :: Tpm ,
1339+ & self . auth_data ,
1340+ ) ?;
1341+
1342+ if let NativeResult :: PrepareKeyAttestation (
1343+ PrepareKeyAttestationResult :: ActivateCredential {
1344+ name,
1345+ public,
1346+ attesting_key_pub,
1347+ } ,
1348+ ) = res
1349+ {
1350+ Ok ( PrepareActivateCredential {
1351+ name : name. to_vec ( ) ,
1352+ public : public. to_vec ( ) ,
1353+ attesting_key_pub : attesting_key_pub. to_vec ( ) ,
1354+ } )
1355+ } else {
1356+ // Should really not be reached given the checks we do, but it's not impossible if some
1357+ // changes happen in the interface
1358+ Err ( Error :: Client ( ClientErrorKind :: InvalidServiceResponseType ) )
1359+ }
1360+ }
1361+
1362+ /// **[Cryptographic Operation]** Perform a key attestation operation via
1363+ /// ActivateCredential
1364+ ///
1365+ /// **This key attestation method is TPM-specific**
1366+ ///
1367+ /// You can see more details on the inner-workings, and on the requirements
1368+ /// for this operation [here](https://parallaxsecond.github.io/parsec-book/parsec_client/operations/attest_key.html).
1369+ ///
1370+ /// Before performing an ActivateCredential attestation you must compute
1371+ /// the `credential_blob` and `secret` parameters using the outputs from
1372+ /// the `prepare_activate_credential` method.
1373+ pub fn activate_credential_attestation (
1374+ & self ,
1375+ attested_key_name : String ,
1376+ attesting_key_name : Option < String > ,
1377+ credential_blob : Vec < u8 > ,
1378+ secret : Vec < u8 > ,
1379+ ) -> Result < Vec < u8 > > {
1380+ self . can_use_provider ( ProviderId :: Tpm ) ?;
1381+
1382+ let op = AttestKey :: ActivateCredential {
1383+ attested_key_name,
1384+ attesting_key_name,
1385+ credential_blob : credential_blob. into ( ) ,
1386+ secret : secret. into ( ) ,
1387+ } ;
1388+
1389+ let res = self . op_client . process_operation (
1390+ NativeOperation :: AttestKey ( op) ,
1391+ ProviderId :: Tpm ,
1392+ & self . auth_data ,
1393+ ) ?;
1394+
1395+ if let NativeResult :: AttestKey ( AttestKeyResult :: ActivateCredential { credential } ) = res {
1396+ Ok ( credential. to_vec ( ) )
1397+ } else {
1398+ // Should really not be reached given the checks we do, but it's not impossible if some
1399+ // changes happen in the interface
1400+ Err ( Error :: Client ( ClientErrorKind :: InvalidServiceResponseType ) )
1401+ }
1402+ }
1403+
13121404 fn can_provide_crypto ( & self ) -> Result < ProviderId > {
13131405 match self . implicit_provider {
13141406 ProviderId :: Core => Err ( Error :: Client ( ClientErrorKind :: InvalidProvider ) ) ,
13151407 crypto_provider => Ok ( crypto_provider) ,
13161408 }
13171409 }
1410+
1411+ fn can_use_provider ( & self , provider : ProviderId ) -> Result < ( ) > {
1412+ let providers = self . list_providers ( ) ?;
1413+ if providers. iter ( ) . any ( |prov| prov. id == provider) {
1414+ Ok ( ( ) )
1415+ } else {
1416+ Err ( Error :: Client ( ClientErrorKind :: NoProvider ) )
1417+ }
1418+ }
13181419}
13191420
13201421impl Default for BasicClient {
@@ -1326,3 +1427,15 @@ impl Default for BasicClient {
13261427 }
13271428 }
13281429}
1430+
1431+ /// Wrapper for the data needed to prepare for an
1432+ /// ActivateCredential attestation.
1433+ #[ derive( Debug ) ]
1434+ pub struct PrepareActivateCredential {
1435+ /// TPM name of key to be attested
1436+ pub name : Vec < u8 > ,
1437+ /// Bytes representing the serialized version of the key public parameters
1438+ pub public : Vec < u8 > ,
1439+ /// The public part of the attesting key
1440+ pub attesting_key_pub : Vec < u8 > ,
1441+ }
0 commit comments