@@ -5,6 +5,7 @@ use super::operation_client::OperationClient;
5
5
use crate :: auth:: Authentication ;
6
6
use crate :: error:: { ClientErrorKind , Error , Result } ;
7
7
use log:: { debug, warn} ;
8
+ use parsec_interface:: operations:: attest_key:: { Operation as AttestKey , Result as AttestKeyResult } ;
8
9
use parsec_interface:: operations:: can_do_crypto:: { CheckType , Operation as CanDoCrypto } ;
9
10
use parsec_interface:: operations:: delete_client:: Operation as DeleteClient ;
10
11
use parsec_interface:: operations:: list_authenticators:: {
@@ -15,6 +16,9 @@ use parsec_interface::operations::list_keys::{KeyInfo, Operation as ListKeys};
15
16
use parsec_interface:: operations:: list_opcodes:: Operation as ListOpcodes ;
16
17
use parsec_interface:: operations:: list_providers:: { Operation as ListProviders , ProviderInfo } ;
17
18
use parsec_interface:: operations:: ping:: Operation as Ping ;
19
+ use parsec_interface:: operations:: prepare_key_attestation:: {
20
+ Operation as PrepareKeyAttestation , Result as PrepareKeyAttestationResult ,
21
+ } ;
18
22
use parsec_interface:: operations:: psa_aead_decrypt:: Operation as PsaAeadDecrypt ;
19
23
use parsec_interface:: operations:: psa_aead_encrypt:: Operation as PsaAeadEncrypt ;
20
24
use parsec_interface:: operations:: psa_algorithm:: {
@@ -1309,12 +1313,109 @@ impl BasicClient {
1309
1313
Ok ( ( ) )
1310
1314
}
1311
1315
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
+
1312
1404
fn can_provide_crypto ( & self ) -> Result < ProviderId > {
1313
1405
match self . implicit_provider {
1314
1406
ProviderId :: Core => Err ( Error :: Client ( ClientErrorKind :: InvalidProvider ) ) ,
1315
1407
crypto_provider => Ok ( crypto_provider) ,
1316
1408
}
1317
1409
}
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
+ }
1318
1419
}
1319
1420
1320
1421
impl Default for BasicClient {
@@ -1326,3 +1427,15 @@ impl Default for BasicClient {
1326
1427
}
1327
1428
}
1328
1429
}
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