Skip to content

Commit 119664e

Browse files
authored
Merge pull request #100 from ionut-arm/activate-cred
Add activate credential attestation methods
2 parents 9e7dd11 + d696cc7 commit 119664e

File tree

1 file changed

+113
-0
lines changed

1 file changed

+113
-0
lines changed

src/core/basic_client.rs

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use super::operation_client::OperationClient;
55
use crate::auth::Authentication;
66
use crate::error::{ClientErrorKind, Error, Result};
77
use log::{debug, warn};
8+
use parsec_interface::operations::attest_key::{Operation as AttestKey, Result as AttestKeyResult};
89
use parsec_interface::operations::can_do_crypto::{CheckType, Operation as CanDoCrypto};
910
use parsec_interface::operations::delete_client::Operation as DeleteClient;
1011
use parsec_interface::operations::list_authenticators::{
@@ -15,6 +16,9 @@ use parsec_interface::operations::list_keys::{KeyInfo, Operation as ListKeys};
1516
use parsec_interface::operations::list_opcodes::Operation as ListOpcodes;
1617
use parsec_interface::operations::list_providers::{Operation as ListProviders, ProviderInfo};
1718
use parsec_interface::operations::ping::Operation as Ping;
19+
use parsec_interface::operations::prepare_key_attestation::{
20+
Operation as PrepareKeyAttestation, Result as PrepareKeyAttestationResult,
21+
};
1822
use parsec_interface::operations::psa_aead_decrypt::Operation as PsaAeadDecrypt;
1923
use parsec_interface::operations::psa_aead_encrypt::Operation as PsaAeadEncrypt;
2024
use 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

13201421
impl 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

Comments
 (0)