Skip to content

Commit b4da173

Browse files
committedNov 2, 2021
Add key attestation operations
This commit adds the types for the new key attestation operations and their conversions to/from protobuf. Signed-off-by: Ionut Mihalcea <[email protected]>
1 parent e677bfd commit b4da173

11 files changed

+1052
-15
lines changed
 

‎src/operations/attest_key.rs

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright 2021 Contributors to the Parsec project.
2+
// SPDX-License-Identifier: Apache-2.0
3+
//! # AttestKey operation
4+
//!
5+
//! Produce an attestation token as proof that the given
6+
//! key was produced and is stored in the hardware backend.
7+
use derivative::Derivative;
8+
use zeroize::Zeroizing;
9+
10+
/// Native operation for key attestation
11+
#[derive(Derivative)]
12+
#[derivative(Debug)]
13+
#[non_exhaustive]
14+
pub enum Operation {
15+
/// Attestation via TPM 2.0 ActivateCredential operation
16+
ActivateCredential {
17+
/// Name of key to be attested
18+
attested_key_name: String,
19+
/// Blob of data representing the encrypted credential
20+
#[derivative(Debug = "ignore")]
21+
credential_blob: Zeroizing<Vec<u8>>,
22+
/// Blob of data representing the encrypted secret
23+
#[derivative(Debug = "ignore")]
24+
secret: Zeroizing<Vec<u8>>,
25+
/// Name of key to be used for attesting
26+
attesting_key_name: Option<String>,
27+
},
28+
}
29+
30+
/// Native result of key attestation
31+
#[derive(Derivative)]
32+
#[derivative(Debug)]
33+
#[non_exhaustive]
34+
pub enum Result {
35+
/// Result of attestation via TPM 2.0 ActivateCredential operation
36+
ActivateCredential {
37+
/// Decrypted credential
38+
#[derivative(Debug = "ignore")]
39+
credential: Zeroizing<Vec<u8>>,
40+
},
41+
}

‎src/operations/mod.rs

+40
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ pub mod delete_client;
3535
pub mod list_clients;
3636
pub mod psa_generate_random;
3737
pub mod psa_raw_key_agreement;
38+
pub mod attest_key;
39+
pub mod prepare_key_attestation;
3840

3941
pub use psa_crypto::types::algorithm as psa_algorithm;
4042
pub use psa_crypto::types::key as psa_key_attributes;
@@ -97,6 +99,10 @@ pub enum NativeOperation {
9799
PsaSignMessage(psa_sign_message::Operation),
98100
/// PsaVerifyMessage operation
99101
PsaVerifyMessage(psa_verify_message::Operation),
102+
/// AttestKey operation
103+
AttestKey(attest_key::Operation),
104+
/// PrepareKeyAttestation operation
105+
PrepareKeyAttestation(prepare_key_attestation::Operation),
100106
}
101107

102108
impl NativeOperation {
@@ -129,6 +135,8 @@ impl NativeOperation {
129135
NativeOperation::PsaRawKeyAgreement(_) => Opcode::PsaRawKeyAgreement,
130136
NativeOperation::PsaSignMessage(_) => Opcode::PsaSignMessage,
131137
NativeOperation::PsaVerifyMessage(_) => Opcode::PsaVerifyMessage,
138+
NativeOperation::AttestKey(_) => Opcode::AttestKey,
139+
NativeOperation::PrepareKeyAttestation(_) => Opcode::PrepareKeyAttestation,
132140
}
133141
}
134142
}
@@ -189,6 +197,10 @@ pub enum NativeResult {
189197
PsaSignMessage(psa_sign_message::Result),
190198
/// PsaVerifyMessage result
191199
PsaVerifyMessage(psa_verify_message::Result),
200+
/// AttestKey result
201+
AttestKey(attest_key::Result),
202+
/// AttestKey result
203+
PrepareKeyAttestation(prepare_key_attestation::Result),
192204
}
193205

194206
impl NativeResult {
@@ -221,6 +233,8 @@ impl NativeResult {
221233
NativeResult::PsaRawKeyAgreement(_) => Opcode::PsaRawKeyAgreement,
222234
NativeResult::PsaSignMessage(_) => Opcode::PsaSignMessage,
223235
NativeResult::PsaVerifyMessage(_) => Opcode::PsaVerifyMessage,
236+
NativeResult::AttestKey(_) => Opcode::AttestKey,
237+
NativeResult::PrepareKeyAttestation(_) => Opcode::PrepareKeyAttestation,
224238
}
225239
}
226240
}
@@ -393,22 +407,36 @@ impl From<psa_hash_compare::Operation> for NativeOperation {
393407
NativeOperation::PsaHashCompare(op)
394408
}
395409
}
410+
396411
impl From<psa_raw_key_agreement::Operation> for NativeOperation {
397412
fn from(op: psa_raw_key_agreement::Operation) -> Self {
398413
NativeOperation::PsaRawKeyAgreement(op)
399414
}
400415
}
416+
401417
impl From<psa_sign_message::Operation> for NativeOperation {
402418
fn from(op: psa_sign_message::Operation) -> Self {
403419
NativeOperation::PsaSignMessage(op)
404420
}
405421
}
422+
406423
impl From<psa_verify_message::Operation> for NativeOperation {
407424
fn from(op: psa_verify_message::Operation) -> Self {
408425
NativeOperation::PsaVerifyMessage(op)
409426
}
410427
}
411428

429+
impl From<attest_key::Operation> for NativeOperation {
430+
fn from(op: attest_key::Operation) -> Self {
431+
NativeOperation::AttestKey(op)
432+
}
433+
}
434+
impl From<prepare_key_attestation::Operation> for NativeOperation {
435+
fn from(op: prepare_key_attestation::Operation) -> Self {
436+
NativeOperation::PrepareKeyAttestation(op)
437+
}
438+
}
439+
412440
impl From<list_providers::Result> for NativeResult {
413441
fn from(op: list_providers::Result) -> Self {
414442
NativeResult::ListProviders(op)
@@ -564,3 +592,15 @@ impl From<psa_verify_message::Result> for NativeResult {
564592
NativeResult::PsaVerifyMessage(op)
565593
}
566594
}
595+
596+
impl From<attest_key::Result> for NativeResult {
597+
fn from(op: attest_key::Result) -> Self {
598+
NativeResult::AttestKey(op)
599+
}
600+
}
601+
602+
impl From<prepare_key_attestation::Result> for NativeResult {
603+
fn from(op: prepare_key_attestation::Result) -> Self {
604+
NativeResult::PrepareKeyAttestation(op)
605+
}
606+
}
+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2021 Contributors to the Parsec project.
2+
// SPDX-License-Identifier: Apache-2.0
3+
//! # PrepareKeyAttestation operation
4+
//!
5+
//! Produce any parameters required for the AttestKey operation
6+
use derivative::Derivative;
7+
use zeroize::Zeroizing;
8+
9+
/// Native operation for retrieving key attestation parameters
10+
#[derive(Debug)]
11+
#[non_exhaustive]
12+
pub enum Operation {
13+
/// Get parameters for TPM 2.0 ActivateCredential operation
14+
ActivateCredential {
15+
/// Name of key to be attested
16+
attested_key_name: String,
17+
/// Name of key to be used for attesting
18+
attesting_key_name: Option<String>,
19+
},
20+
}
21+
22+
/// Native result of retrieving key attestation parameters
23+
#[derive(Derivative)]
24+
#[derivative(Debug)]
25+
#[non_exhaustive]
26+
pub enum Result {
27+
/// Parameters for TPM 2.0 ActivateCredential operation
28+
ActivateCredential {
29+
/// TPM name of key to be attested
30+
#[derivative(Debug = "ignore")]
31+
name: Zeroizing<Vec<u8>>,
32+
/// TPM public key parameters of object to be attested
33+
#[derivative(Debug = "ignore")]
34+
public: Zeroizing<Vec<u8>>,
35+
/// Public part of attesting key
36+
#[derivative(Debug = "ignore")]
37+
attesting_key_pub: Zeroizing<Vec<u8>>,
38+
},
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,326 @@
1+
// Copyright 2021 Contributors to the Parsec project.
2+
// SPDX-License-Identifier: Apache-2.0
3+
use super::generated_ops::attest_key::{
4+
attestation_mechanism_params, attestation_output, AttestationMechanismParams,
5+
AttestationOutput, Operation as OperationProto, Result as ResultProto,
6+
};
7+
use crate::operations::attest_key::{Operation, Result};
8+
use crate::requests::ResponseStatus;
9+
use log::error;
10+
use std::convert::TryFrom;
11+
12+
impl TryFrom<Operation> for OperationProto {
13+
type Error = ResponseStatus;
14+
15+
fn try_from(op: Operation) -> std::result::Result<Self, Self::Error> {
16+
match op {
17+
Operation::ActivateCredential {
18+
attested_key_name,
19+
attesting_key_name,
20+
credential_blob,
21+
secret,
22+
} => Ok(OperationProto {
23+
attested_key_name,
24+
attesting_key_name: attesting_key_name.unwrap_or_default(),
25+
parameters: Some(AttestationMechanismParams {
26+
mechanism: Some(attestation_mechanism_params::Mechanism::ActivateCredential(
27+
attestation_mechanism_params::ActivateCredential {
28+
credential_blob: credential_blob.to_vec(),
29+
secret: secret.to_vec(),
30+
},
31+
)),
32+
}),
33+
}),
34+
}
35+
}
36+
}
37+
38+
impl TryFrom<OperationProto> for Operation {
39+
type Error = ResponseStatus;
40+
41+
fn try_from(proto_op: OperationProto) -> std::result::Result<Self, Self::Error> {
42+
match proto_op.parameters {
43+
Some(AttestationMechanismParams {
44+
mechanism:
45+
Some(attestation_mechanism_params::Mechanism::ActivateCredential(
46+
attestation_mechanism_params::ActivateCredential {
47+
credential_blob,
48+
secret,
49+
},
50+
)),
51+
}) => Ok(Operation::ActivateCredential {
52+
attested_key_name: proto_op.attested_key_name,
53+
attesting_key_name: if proto_op.attesting_key_name.is_empty() {
54+
None
55+
} else {
56+
Some(proto_op.attesting_key_name)
57+
},
58+
credential_blob: credential_blob.into(),
59+
secret: secret.into(),
60+
}),
61+
_ => {
62+
error!("The encoding of the operation does not follow the expected pattern");
63+
Err(ResponseStatus::InvalidEncoding)
64+
}
65+
}
66+
}
67+
}
68+
69+
impl TryFrom<Result> for ResultProto {
70+
type Error = ResponseStatus;
71+
72+
fn try_from(op: Result) -> std::result::Result<Self, Self::Error> {
73+
match op {
74+
Result::ActivateCredential { credential } => Ok(ResultProto {
75+
output: Some(AttestationOutput {
76+
mechanism: Some(attestation_output::Mechanism::ActivateCredential(
77+
attestation_output::ActivateCredential {
78+
credential: credential.to_vec(),
79+
},
80+
)),
81+
}),
82+
}),
83+
}
84+
}
85+
}
86+
87+
impl TryFrom<ResultProto> for Result {
88+
type Error = ResponseStatus;
89+
90+
fn try_from(proto_op: ResultProto) -> std::result::Result<Self, Self::Error> {
91+
match proto_op {
92+
ResultProto {
93+
output:
94+
Some(AttestationOutput {
95+
mechanism:
96+
Some(attestation_output::Mechanism::ActivateCredential(
97+
attestation_output::ActivateCredential { credential },
98+
)),
99+
}),
100+
} => Ok(Result::ActivateCredential {
101+
credential: credential.into(),
102+
}),
103+
_ => {
104+
error!("The encoding of the result does not follow the expected pattern");
105+
Err(ResponseStatus::InvalidEncoding)
106+
}
107+
}
108+
}
109+
}
110+
111+
#[cfg(test)]
112+
mod test {
113+
use super::super::generated_ops::attest_key::{
114+
attestation_mechanism_params, attestation_output, AttestationMechanismParams,
115+
AttestationOutput, Operation as OperationProto, Result as ResultProto,
116+
};
117+
use super::super::{Convert, ProtobufConverter};
118+
use crate::operations::{
119+
attest_key::Operation, attest_key::Result, NativeOperation, NativeResult,
120+
};
121+
use crate::requests::Opcode;
122+
use std::convert::TryInto;
123+
124+
static CONVERTER: ProtobufConverter = ProtobufConverter {};
125+
126+
#[test]
127+
fn attest_key_op_from_proto() {
128+
let op_attested_key_name = String::from("attested key name");
129+
let op_attesting_key_name = String::from("attesting key name");
130+
let op_credential_blob = vec![0xaa; 32];
131+
let op_secret = vec![0x11; 16];
132+
133+
let proto = OperationProto {
134+
attested_key_name: op_attested_key_name.clone(),
135+
attesting_key_name: op_attesting_key_name.clone(),
136+
parameters: Some(AttestationMechanismParams {
137+
mechanism: Some(attestation_mechanism_params::Mechanism::ActivateCredential(
138+
attestation_mechanism_params::ActivateCredential {
139+
credential_blob: op_credential_blob.clone(),
140+
secret: op_secret.clone(),
141+
},
142+
)),
143+
}),
144+
};
145+
146+
let op: Operation = proto.try_into().expect("Failed conversion");
147+
let Operation::ActivateCredential {
148+
attested_key_name,
149+
attesting_key_name,
150+
credential_blob,
151+
secret,
152+
} = op;
153+
assert_eq!(attested_key_name, op_attested_key_name);
154+
assert_eq!(
155+
attesting_key_name.unwrap_or_default(),
156+
op_attesting_key_name
157+
);
158+
assert_eq!(credential_blob.to_vec(), op_credential_blob);
159+
assert_eq!(secret.to_vec(), op_secret);
160+
}
161+
162+
#[test]
163+
fn attest_key_proto_no_attesting() {
164+
let op_attested_key_name = String::from("attested key name");
165+
let op_credential_blob = vec![0xaa; 32];
166+
let op_secret = vec![0x11; 16];
167+
168+
let proto = OperationProto {
169+
attested_key_name: op_attested_key_name,
170+
attesting_key_name: String::new(),
171+
parameters: Some(AttestationMechanismParams {
172+
mechanism: Some(attestation_mechanism_params::Mechanism::ActivateCredential(
173+
attestation_mechanism_params::ActivateCredential {
174+
credential_blob: op_credential_blob,
175+
secret: op_secret,
176+
},
177+
)),
178+
}),
179+
};
180+
181+
let op: Operation = proto.try_into().expect("Failed conversion");
182+
let Operation::ActivateCredential {
183+
attesting_key_name, ..
184+
} = op;
185+
assert!(attesting_key_name.is_none());
186+
}
187+
188+
#[test]
189+
fn attest_key_proto_from_op() {
190+
let op_attested_key_name = String::from("attested key name");
191+
let op_attesting_key_name = String::from("attesting key name");
192+
let op_credential_blob = vec![0xaa; 32];
193+
let op_secret = vec![0x11; 16];
194+
195+
let op = Operation::ActivateCredential {
196+
attested_key_name: op_attested_key_name.clone(),
197+
attesting_key_name: Some(op_attesting_key_name.clone()),
198+
credential_blob: op_credential_blob.clone().into(),
199+
secret: op_secret.clone().into(),
200+
};
201+
202+
let proto: OperationProto = op.try_into().expect("Failed conversion");
203+
if let OperationProto {
204+
attested_key_name,
205+
attesting_key_name,
206+
parameters:
207+
Some(AttestationMechanismParams {
208+
mechanism:
209+
Some(attestation_mechanism_params::Mechanism::ActivateCredential(
210+
attestation_mechanism_params::ActivateCredential {
211+
credential_blob,
212+
secret,
213+
},
214+
)),
215+
}),
216+
} = proto
217+
{
218+
assert_eq!(attested_key_name, op_attested_key_name);
219+
assert_eq!(attesting_key_name, op_attesting_key_name);
220+
assert_eq!(credential_blob, op_credential_blob);
221+
assert_eq!(secret, op_secret);
222+
}
223+
}
224+
225+
#[test]
226+
fn attest_key_op_no_attesting() {
227+
let op_attested_key_name = String::from("attested key name");
228+
let op_credential_blob = vec![0xaa; 32];
229+
let op_secret = vec![0x11; 16];
230+
231+
let op = Operation::ActivateCredential {
232+
attested_key_name: op_attested_key_name,
233+
attesting_key_name: None,
234+
credential_blob: op_credential_blob.into(),
235+
secret: op_secret.into(),
236+
};
237+
238+
let proto: OperationProto = op.try_into().expect("Failed conversion");
239+
assert_eq!(proto.attesting_key_name, String::new());
240+
}
241+
242+
#[test]
243+
fn attest_key_op_e2e() {
244+
let op_attested_key_name = String::from("attested key name");
245+
let op_attesting_key_name = String::from("attesting key name");
246+
let op_credential_blob = vec![0xaa; 32];
247+
let op_secret = vec![0x11; 16];
248+
249+
let op = Operation::ActivateCredential {
250+
attested_key_name: op_attested_key_name,
251+
attesting_key_name: Some(op_attesting_key_name),
252+
credential_blob: op_credential_blob.into(),
253+
secret: op_secret.into(),
254+
};
255+
256+
let body = CONVERTER
257+
.operation_to_body(NativeOperation::AttestKey(op))
258+
.expect("Failed to convert to body");
259+
260+
let _ = CONVERTER
261+
.body_to_operation(body, Opcode::AttestKey)
262+
.expect("Failed to convert to operation");
263+
}
264+
265+
#[test]
266+
fn attest_key_resp_from_proto() {
267+
let resp_credential = vec![0xbb; 32];
268+
269+
let proto = ResultProto {
270+
output: Some(AttestationOutput {
271+
mechanism: Some(attestation_output::Mechanism::ActivateCredential(
272+
attestation_output::ActivateCredential {
273+
credential: resp_credential.clone(),
274+
},
275+
)),
276+
}),
277+
};
278+
279+
let resp: Result = proto.try_into().expect("Failed conversion");
280+
281+
let Result::ActivateCredential { credential } = resp;
282+
283+
assert_eq!(credential.to_vec(), resp_credential);
284+
}
285+
286+
#[test]
287+
fn attest_key_resp_to_proto() {
288+
let resp_credential = vec![0xbb; 32];
289+
290+
let resp = Result::ActivateCredential {
291+
credential: resp_credential.clone().into(),
292+
};
293+
294+
let proto: ResultProto = resp.try_into().expect("Failed conversion");
295+
296+
if let ResultProto {
297+
output:
298+
Some(AttestationOutput {
299+
mechanism:
300+
Some(attestation_output::Mechanism::ActivateCredential(
301+
attestation_output::ActivateCredential { credential },
302+
)),
303+
}),
304+
} = proto
305+
{
306+
assert_eq!(credential.to_vec(), resp_credential);
307+
}
308+
}
309+
310+
#[test]
311+
fn attest_key_resp_e2e() {
312+
let resp_credential = vec![0xbb; 32];
313+
314+
let resp = Result::ActivateCredential {
315+
credential: resp_credential.into(),
316+
};
317+
318+
let body = CONVERTER
319+
.result_to_body(NativeResult::AttestKey(resp))
320+
.expect("Failed to convert to body");
321+
322+
let _ = CONVERTER
323+
.body_to_result(body, Opcode::AttestKey)
324+
.expect("Failed to convert to operation");
325+
}
326+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,362 @@
1+
// Copyright 2021 Contributors to the Parsec project.
2+
// SPDX-License-Identifier: Apache-2.0
3+
use super::generated_ops::prepare_key_attestation::{
4+
prepare_key_attestation_output, prepare_key_attestation_params, Operation as OperationProto,
5+
PrepareKeyAttestationOutput, PrepareKeyAttestationParams, Result as ResultProto,
6+
};
7+
use crate::operations::prepare_key_attestation::{Operation, Result};
8+
use crate::requests::ResponseStatus;
9+
use log::error;
10+
use std::convert::TryFrom;
11+
12+
impl TryFrom<Operation> for OperationProto {
13+
type Error = ResponseStatus;
14+
15+
fn try_from(op: Operation) -> std::result::Result<Self, Self::Error> {
16+
match op {
17+
Operation::ActivateCredential {
18+
attested_key_name,
19+
attesting_key_name,
20+
} => Ok(OperationProto {
21+
parameters: Some(PrepareKeyAttestationParams {
22+
mechanism: Some(
23+
prepare_key_attestation_params::Mechanism::ActivateCredential(
24+
prepare_key_attestation_params::ActivateCredential {
25+
attested_key_name,
26+
attesting_key_name: attesting_key_name.unwrap_or_default(),
27+
},
28+
),
29+
),
30+
}),
31+
}),
32+
}
33+
}
34+
}
35+
36+
impl TryFrom<OperationProto> for Operation {
37+
type Error = ResponseStatus;
38+
39+
fn try_from(op: OperationProto) -> std::result::Result<Self, Self::Error> {
40+
match op {
41+
OperationProto {
42+
parameters:
43+
Some(PrepareKeyAttestationParams {
44+
mechanism:
45+
Some(prepare_key_attestation_params::Mechanism::ActivateCredential(
46+
prepare_key_attestation_params::ActivateCredential {
47+
attested_key_name,
48+
attesting_key_name,
49+
},
50+
)),
51+
}),
52+
} => Ok(Operation::ActivateCredential {
53+
attested_key_name,
54+
attesting_key_name: if attesting_key_name.is_empty() {
55+
None
56+
} else {
57+
Some(attesting_key_name)
58+
},
59+
}),
60+
_ => {
61+
error!("The encoding of the operation does not follow the expected pattern");
62+
Err(ResponseStatus::InvalidEncoding)
63+
}
64+
}
65+
}
66+
}
67+
68+
impl TryFrom<Result> for ResultProto {
69+
type Error = ResponseStatus;
70+
71+
fn try_from(op: Result) -> std::result::Result<Self, Self::Error> {
72+
match op {
73+
Result::ActivateCredential {
74+
name,
75+
public,
76+
attesting_key_pub,
77+
} => Ok(ResultProto {
78+
output: Some(PrepareKeyAttestationOutput {
79+
mechanism: Some(
80+
prepare_key_attestation_output::Mechanism::ActivateCredential(
81+
prepare_key_attestation_output::ActivateCredential {
82+
name: name.to_vec(),
83+
public: public.to_vec(),
84+
attesting_key_pub: attesting_key_pub.to_vec(),
85+
},
86+
),
87+
),
88+
}),
89+
}),
90+
}
91+
}
92+
}
93+
94+
impl TryFrom<ResultProto> for Result {
95+
type Error = ResponseStatus;
96+
97+
fn try_from(op: ResultProto) -> std::result::Result<Self, Self::Error> {
98+
match op {
99+
ResultProto {
100+
output:
101+
Some(PrepareKeyAttestationOutput {
102+
mechanism:
103+
Some(prepare_key_attestation_output::Mechanism::ActivateCredential(
104+
prepare_key_attestation_output::ActivateCredential {
105+
name,
106+
public,
107+
attesting_key_pub,
108+
},
109+
)),
110+
}),
111+
} => Ok(Result::ActivateCredential {
112+
name: name.into(),
113+
public: public.into(),
114+
attesting_key_pub: attesting_key_pub.into(),
115+
}),
116+
_ => {
117+
error!("The encoding of the operation does not follow the expected pattern");
118+
Err(ResponseStatus::InvalidEncoding)
119+
}
120+
}
121+
}
122+
}
123+
124+
#[cfg(test)]
125+
mod test {
126+
use super::super::generated_ops::prepare_key_attestation::{
127+
prepare_key_attestation_output, prepare_key_attestation_params,
128+
Operation as OperationProto, PrepareKeyAttestationOutput, PrepareKeyAttestationParams,
129+
Result as ResultProto,
130+
};
131+
use super::super::{Convert, ProtobufConverter};
132+
use crate::operations::{
133+
prepare_key_attestation::Operation, prepare_key_attestation::Result, NativeOperation,
134+
NativeResult,
135+
};
136+
use crate::requests::Opcode;
137+
use std::convert::TryInto;
138+
139+
static CONVERTER: ProtobufConverter = ProtobufConverter {};
140+
141+
#[test]
142+
fn prepare_key_attestation_op_from_proto() {
143+
let op_attested_key_name = String::from("attested key name");
144+
let op_attesting_key_name = String::from("attesting key name");
145+
146+
let proto = OperationProto {
147+
parameters: Some(PrepareKeyAttestationParams {
148+
mechanism: Some(
149+
prepare_key_attestation_params::Mechanism::ActivateCredential(
150+
prepare_key_attestation_params::ActivateCredential {
151+
attested_key_name: op_attested_key_name.clone(),
152+
attesting_key_name: op_attesting_key_name.clone(),
153+
},
154+
),
155+
),
156+
}),
157+
};
158+
159+
let op: Operation = proto.try_into().expect("Conversion failed");
160+
161+
let Operation::ActivateCredential {
162+
attested_key_name,
163+
attesting_key_name,
164+
} = op;
165+
166+
assert_eq!(attested_key_name, op_attested_key_name);
167+
assert_eq!(
168+
attesting_key_name.expect("Attesting key name was empty"),
169+
op_attesting_key_name
170+
);
171+
}
172+
173+
#[test]
174+
fn prepare_key_attestation_proto_no_attesting() {
175+
let op_attested_key_name = String::from("attested key name");
176+
177+
let proto = OperationProto {
178+
parameters: Some(PrepareKeyAttestationParams {
179+
mechanism: Some(
180+
prepare_key_attestation_params::Mechanism::ActivateCredential(
181+
prepare_key_attestation_params::ActivateCredential {
182+
attested_key_name: op_attested_key_name,
183+
attesting_key_name: String::new(),
184+
},
185+
),
186+
),
187+
}),
188+
};
189+
190+
let op: Operation = proto.try_into().expect("Conversion failed");
191+
192+
let Operation::ActivateCredential {
193+
attesting_key_name, ..
194+
} = op;
195+
196+
assert!(attesting_key_name.is_none());
197+
}
198+
199+
#[test]
200+
fn prepare_key_attestation_op_to_proto() {
201+
let op_attested_key_name = String::from("attested key name");
202+
let op_attesting_key_name = String::from("attesting key name");
203+
204+
let op: Operation = Operation::ActivateCredential {
205+
attested_key_name: op_attested_key_name.clone(),
206+
attesting_key_name: Some(op_attesting_key_name.clone()),
207+
};
208+
209+
let proto: OperationProto = op.try_into().expect("Conversion failed");
210+
211+
if let OperationProto {
212+
parameters:
213+
Some(PrepareKeyAttestationParams {
214+
mechanism:
215+
Some(prepare_key_attestation_params::Mechanism::ActivateCredential(
216+
prepare_key_attestation_params::ActivateCredential {
217+
attested_key_name,
218+
attesting_key_name,
219+
},
220+
)),
221+
}),
222+
} = proto
223+
{
224+
assert_eq!(attested_key_name, op_attested_key_name);
225+
assert_eq!(attesting_key_name, op_attesting_key_name);
226+
}
227+
}
228+
229+
#[test]
230+
fn prepare_key_attestation_op_no_attesting() {
231+
let op_attested_key_name = String::from("attested key name");
232+
233+
let op: Operation = Operation::ActivateCredential {
234+
attested_key_name: op_attested_key_name,
235+
attesting_key_name: None,
236+
};
237+
238+
let proto: OperationProto = op.try_into().expect("Conversion failed");
239+
240+
if let OperationProto {
241+
parameters:
242+
Some(PrepareKeyAttestationParams {
243+
mechanism:
244+
Some(prepare_key_attestation_params::Mechanism::ActivateCredential(
245+
prepare_key_attestation_params::ActivateCredential {
246+
attesting_key_name,
247+
..
248+
},
249+
)),
250+
}),
251+
} = proto
252+
{
253+
assert_eq!(attesting_key_name, String::new());
254+
}
255+
}
256+
257+
#[test]
258+
fn prepare_key_attestation_op_e2e() {
259+
let op_attested_key_name = String::from("attested key name");
260+
let op_attesting_key_name = String::from("attesting key name");
261+
262+
let op: Operation = Operation::ActivateCredential {
263+
attested_key_name: op_attested_key_name,
264+
attesting_key_name: Some(op_attesting_key_name),
265+
};
266+
267+
let body = CONVERTER
268+
.operation_to_body(NativeOperation::PrepareKeyAttestation(op))
269+
.expect("Failed to convert to body");
270+
271+
let _ = CONVERTER
272+
.body_to_operation(body, Opcode::PrepareKeyAttestation)
273+
.expect("Failed to convert to operation");
274+
}
275+
276+
#[test]
277+
fn prepare_key_attestation_resp_to_proto() {
278+
let resp_name = vec![0xff; 32];
279+
let resp_public = vec![0xcc; 32];
280+
let resp_attesting_key_pub = vec![0x22; 32];
281+
282+
let result = Result::ActivateCredential {
283+
name: resp_name.clone().into(),
284+
public: resp_public.clone().into(),
285+
attesting_key_pub: resp_attesting_key_pub.clone().into(),
286+
};
287+
288+
let proto: ResultProto = result.try_into().expect("Conversion failed");
289+
if let ResultProto {
290+
output:
291+
Some(PrepareKeyAttestationOutput {
292+
mechanism:
293+
Some(prepare_key_attestation_output::Mechanism::ActivateCredential(
294+
prepare_key_attestation_output::ActivateCredential {
295+
name,
296+
public,
297+
attesting_key_pub,
298+
},
299+
)),
300+
}),
301+
} = proto
302+
{
303+
assert_eq!(name, resp_name);
304+
assert_eq!(public, resp_public);
305+
assert_eq!(attesting_key_pub, resp_attesting_key_pub);
306+
}
307+
}
308+
309+
#[test]
310+
fn prepare_key_attestation_resp_from_proto() {
311+
let resp_name = vec![0xff; 32];
312+
let resp_public = vec![0xcc; 32];
313+
let resp_attesting_key_pub = vec![0x22; 32];
314+
315+
let proto = ResultProto {
316+
output: Some(PrepareKeyAttestationOutput {
317+
mechanism: Some(
318+
prepare_key_attestation_output::Mechanism::ActivateCredential(
319+
prepare_key_attestation_output::ActivateCredential {
320+
name: resp_name.clone(),
321+
public: resp_public.clone(),
322+
attesting_key_pub: resp_attesting_key_pub.clone(),
323+
},
324+
),
325+
),
326+
}),
327+
};
328+
329+
let result: Result = proto.try_into().expect("Conversion failed");
330+
331+
let Result::ActivateCredential {
332+
name,
333+
public,
334+
attesting_key_pub,
335+
} = result;
336+
337+
assert_eq!(name.to_vec(), resp_name);
338+
assert_eq!(public.to_vec(), resp_public);
339+
assert_eq!(attesting_key_pub.to_vec(), resp_attesting_key_pub);
340+
}
341+
342+
#[test]
343+
fn prepare_key_attestation_resp_e2e() {
344+
let resp_name = vec![0xff; 32];
345+
let resp_public = vec![0xcc; 32];
346+
let resp_attesting_key_pub = vec![0x22; 32];
347+
348+
let result = Result::ActivateCredential {
349+
name: resp_name.into(),
350+
public: resp_public.into(),
351+
attesting_key_pub: resp_attesting_key_pub.into(),
352+
};
353+
354+
let body = CONVERTER
355+
.result_to_body(NativeResult::PrepareKeyAttestation(result))
356+
.expect("Failed to convert to body");
357+
358+
let _ = CONVERTER
359+
.body_to_result(body, Opcode::PrepareKeyAttestation)
360+
.expect("Failed to convert to operation");
361+
}
362+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#[derive(Clone, PartialEq, ::prost::Message)]
2+
pub struct AttestationMechanismParams {
3+
#[prost(oneof="attestation_mechanism_params::Mechanism", tags="1")]
4+
pub mechanism: ::core::option::Option<attestation_mechanism_params::Mechanism>,
5+
}
6+
/// Nested message and enum types in `AttestationMechanismParams`.
7+
pub mod attestation_mechanism_params {
8+
#[derive(Clone, PartialEq, ::prost::Message)]
9+
pub struct ActivateCredential {
10+
#[prost(bytes="vec", tag="1")]
11+
pub credential_blob: ::prost::alloc::vec::Vec<u8>,
12+
#[prost(bytes="vec", tag="2")]
13+
pub secret: ::prost::alloc::vec::Vec<u8>,
14+
}
15+
#[derive(Clone, PartialEq, ::prost::Oneof)]
16+
pub enum Mechanism {
17+
#[prost(message, tag="1")]
18+
ActivateCredential(ActivateCredential),
19+
}
20+
}
21+
#[derive(Clone, PartialEq, ::prost::Message)]
22+
pub struct Operation {
23+
#[prost(string, tag="1")]
24+
pub attested_key_name: ::prost::alloc::string::String,
25+
#[prost(message, optional, tag="2")]
26+
pub parameters: ::core::option::Option<AttestationMechanismParams>,
27+
#[prost(string, tag="3")]
28+
pub attesting_key_name: ::prost::alloc::string::String,
29+
}
30+
#[derive(Clone, PartialEq, ::prost::Message)]
31+
pub struct AttestationOutput {
32+
#[prost(oneof="attestation_output::Mechanism", tags="1")]
33+
pub mechanism: ::core::option::Option<attestation_output::Mechanism>,
34+
}
35+
/// Nested message and enum types in `AttestationOutput`.
36+
pub mod attestation_output {
37+
#[derive(Clone, PartialEq, ::prost::Message)]
38+
pub struct ActivateCredential {
39+
#[prost(bytes="vec", tag="1")]
40+
pub credential: ::prost::alloc::vec::Vec<u8>,
41+
}
42+
#[derive(Clone, PartialEq, ::prost::Oneof)]
43+
pub enum Mechanism {
44+
#[prost(message, tag="1")]
45+
ActivateCredential(ActivateCredential),
46+
}
47+
}
48+
#[derive(Clone, PartialEq, ::prost::Message)]
49+
pub struct Result {
50+
#[prost(message, optional, tag="1")]
51+
pub output: ::core::option::Option<AttestationOutput>,
52+
}

‎src/operations_protobuf/generated_ops/mod.rs

+97-12
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ pub mod psa_generate_random;
2929
pub mod psa_hash_compute;
3030
pub mod psa_hash_compare;
3131
pub mod psa_raw_key_agreement;
32+
pub mod attest_key;
33+
pub mod prepare_key_attestation;
3234

3335
use zeroize::Zeroize;
3436

@@ -154,6 +156,7 @@ empty_clear_message!(psa_verify_hash::Result);
154156
empty_clear_message!(psa_verify_message::Result);
155157
empty_clear_message!(psa_generate_random::Operation);
156158
empty_clear_message!(psa_hash_compare::Result);
159+
empty_clear_message!(prepare_key_attestation::Operation);
157160

158161
impl ClearProtoMessage for psa_sign_hash::Operation {
159162
fn clear_message(&mut self) {
@@ -226,11 +229,15 @@ impl ClearProtoMessage for psa_asymmetric_decrypt::Operation {
226229
}
227230

228231
impl ClearProtoMessage for psa_asymmetric_encrypt::Result {
229-
fn clear_message(&mut self) { self.ciphertext.zeroize(); }
232+
fn clear_message(&mut self) {
233+
self.ciphertext.zeroize();
234+
}
230235
}
231236

232237
impl ClearProtoMessage for psa_asymmetric_decrypt::Result {
233-
fn clear_message(&mut self) { self.plaintext.zeroize(); }
238+
fn clear_message(&mut self) {
239+
self.plaintext.zeroize();
240+
}
234241
}
235242

236243
impl ClearProtoMessage for psa_aead_encrypt::Operation {
@@ -250,7 +257,9 @@ impl ClearProtoMessage for psa_aead_decrypt::Operation {
250257
}
251258

252259
impl ClearProtoMessage for psa_aead_encrypt::Result {
253-
fn clear_message(&mut self) { self.ciphertext.zeroize(); }
260+
fn clear_message(&mut self) {
261+
self.ciphertext.zeroize();
262+
}
254263
}
255264

256265
impl ClearProtoMessage for psa_aead_decrypt::Result {
@@ -280,15 +289,21 @@ impl ClearProtoMessage for psa_cipher_decrypt::Result {
280289
}
281290

282291
impl ClearProtoMessage for psa_generate_random::Result {
283-
fn clear_message(&mut self) { self.random_bytes.zeroize(); }
292+
fn clear_message(&mut self) {
293+
self.random_bytes.zeroize();
294+
}
284295
}
285296

286297
impl ClearProtoMessage for psa_hash_compute::Operation {
287-
fn clear_message(&mut self) { self.input.zeroize(); }
298+
fn clear_message(&mut self) {
299+
self.input.zeroize();
300+
}
288301
}
289302

290303
impl ClearProtoMessage for psa_hash_compute::Result {
291-
fn clear_message(&mut self) { self.hash.zeroize(); }
304+
fn clear_message(&mut self) {
305+
self.hash.zeroize();
306+
}
292307
}
293308

294309
impl ClearProtoMessage for psa_hash_compare::Operation {
@@ -310,12 +325,82 @@ impl ClearProtoMessage for psa_raw_key_agreement::Result {
310325
}
311326
}
312327

328+
impl ClearProtoMessage for attest_key::Operation {
329+
fn clear_message(&mut self) {
330+
if let attest_key::Operation {
331+
parameters:
332+
Some(attest_key::AttestationMechanismParams {
333+
mechanism:
334+
Some(attest_key::attestation_mechanism_params::Mechanism::ActivateCredential(
335+
attest_key::attestation_mechanism_params::ActivateCredential {
336+
credential_blob,
337+
secret,
338+
},
339+
)),
340+
}),
341+
..
342+
} = self
343+
{
344+
credential_blob.zeroize();
345+
secret.zeroize();
346+
}
347+
}
348+
}
349+
350+
impl ClearProtoMessage for attest_key::Result {
351+
fn clear_message(&mut self) {
352+
if let attest_key::Result {
353+
output:
354+
Some(attest_key::AttestationOutput {
355+
mechanism:
356+
Some(attest_key::attestation_output::Mechanism::ActivateCredential(
357+
attest_key::attestation_output::ActivateCredential { credential },
358+
)),
359+
}),
360+
} = self
361+
{
362+
credential.zeroize();
363+
}
364+
}
365+
}
366+
367+
impl ClearProtoMessage for prepare_key_attestation::Result {
368+
fn clear_message(&mut self) {
369+
if let prepare_key_attestation::Result { output: Some(prepare_key_attestation::PrepareKeyAttestationOutput {
370+
mechanism: Some(prepare_key_attestation::prepare_key_attestation_output::Mechanism::ActivateCredential(
371+
prepare_key_attestation::prepare_key_attestation_output::ActivateCredential {
372+
name, public, attesting_key_pub
373+
}
374+
))
375+
})
376+
} = self {
377+
name.zeroize();
378+
public.zeroize();
379+
attesting_key_pub.zeroize();
380+
}
381+
}
382+
}
383+
313384
#[test]
314385
fn i32_conversions() {
315-
assert_eq!(Cipher::try_from(56).unwrap_err(), ResponseStatus::InvalidEncoding);
316-
assert_eq!(Cipher::try_from(-5).unwrap_err(), ResponseStatus::InvalidEncoding);
317-
assert_eq!(Hash::try_from(89).unwrap_err(), ResponseStatus::InvalidEncoding);
318-
assert_eq!(Hash::try_from(-4).unwrap_err(), ResponseStatus::InvalidEncoding);
319-
assert_eq!(EccFamily::try_from(78).unwrap_err(), ResponseStatus::InvalidEncoding);
320-
386+
assert_eq!(
387+
Cipher::try_from(56).unwrap_err(),
388+
ResponseStatus::InvalidEncoding
389+
);
390+
assert_eq!(
391+
Cipher::try_from(-5).unwrap_err(),
392+
ResponseStatus::InvalidEncoding
393+
);
394+
assert_eq!(
395+
Hash::try_from(89).unwrap_err(),
396+
ResponseStatus::InvalidEncoding
397+
);
398+
assert_eq!(
399+
Hash::try_from(-4).unwrap_err(),
400+
ResponseStatus::InvalidEncoding
401+
);
402+
assert_eq!(
403+
EccFamily::try_from(78).unwrap_err(),
404+
ResponseStatus::InvalidEncoding
405+
);
321406
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#[derive(Clone, PartialEq, ::prost::Message)]
2+
pub struct PrepareKeyAttestationParams {
3+
#[prost(oneof="prepare_key_attestation_params::Mechanism", tags="1")]
4+
pub mechanism: ::core::option::Option<prepare_key_attestation_params::Mechanism>,
5+
}
6+
/// Nested message and enum types in `PrepareKeyAttestationParams`.
7+
pub mod prepare_key_attestation_params {
8+
#[derive(Clone, PartialEq, ::prost::Message)]
9+
pub struct ActivateCredential {
10+
#[prost(string, tag="1")]
11+
pub attested_key_name: ::prost::alloc::string::String,
12+
#[prost(string, tag="2")]
13+
pub attesting_key_name: ::prost::alloc::string::String,
14+
}
15+
#[derive(Clone, PartialEq, ::prost::Oneof)]
16+
pub enum Mechanism {
17+
#[prost(message, tag="1")]
18+
ActivateCredential(ActivateCredential),
19+
}
20+
}
21+
#[derive(Clone, PartialEq, ::prost::Message)]
22+
pub struct Operation {
23+
#[prost(message, optional, tag="1")]
24+
pub parameters: ::core::option::Option<PrepareKeyAttestationParams>,
25+
}
26+
#[derive(Clone, PartialEq, ::prost::Message)]
27+
pub struct PrepareKeyAttestationOutput {
28+
#[prost(oneof="prepare_key_attestation_output::Mechanism", tags="1")]
29+
pub mechanism: ::core::option::Option<prepare_key_attestation_output::Mechanism>,
30+
}
31+
/// Nested message and enum types in `PrepareKeyAttestationOutput`.
32+
pub mod prepare_key_attestation_output {
33+
#[derive(Clone, PartialEq, ::prost::Message)]
34+
pub struct ActivateCredential {
35+
#[prost(bytes="vec", tag="1")]
36+
pub name: ::prost::alloc::vec::Vec<u8>,
37+
#[prost(bytes="vec", tag="2")]
38+
pub public: ::prost::alloc::vec::Vec<u8>,
39+
#[prost(bytes="vec", tag="3")]
40+
pub attesting_key_pub: ::prost::alloc::vec::Vec<u8>,
41+
}
42+
#[derive(Clone, PartialEq, ::prost::Oneof)]
43+
pub enum Mechanism {
44+
#[prost(message, tag="1")]
45+
ActivateCredential(ActivateCredential),
46+
}
47+
}
48+
#[derive(Clone, PartialEq, ::prost::Message)]
49+
pub struct Result {
50+
#[prost(message, optional, tag="1")]
51+
pub output: ::core::option::Option<PrepareKeyAttestationOutput>,
52+
}

‎src/operations_protobuf/mod.rs

+32
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ mod convert_psa_cipher_encrypt;
3131
mod convert_psa_cipher_decrypt;
3232
mod convert_psa_generate_random;
3333
mod convert_psa_raw_key_agreement;
34+
mod convert_attest_key;
35+
mod convert_prepare_key_attestation;
3436

3537
#[rustfmt::skip]
3638
#[allow(unused_qualifications, missing_copy_implementations, clippy::pedantic, clippy::module_inception, clippy::upper_case_acronyms, clippy::enum_variant_names)]
@@ -40,13 +42,15 @@ use crate::operations::{Convert, NativeOperation, NativeResult};
4042
use crate::requests::{
4143
request::RequestBody, response::ResponseBody, BodyType, Opcode, ResponseStatus, Result,
4244
};
45+
use generated_ops::attest_key as attest_key_proto;
4346
use generated_ops::delete_client as delete_client_proto;
4447
use generated_ops::list_authenticators as list_authenticators_proto;
4548
use generated_ops::list_clients as list_clients_proto;
4649
use generated_ops::list_keys as list_keys_proto;
4750
use generated_ops::list_opcodes as list_opcodes_proto;
4851
use generated_ops::list_providers as list_providers_proto;
4952
use generated_ops::ping as ping_proto;
53+
use generated_ops::prepare_key_attestation as prepare_key_attestation_proto;
5054
use generated_ops::psa_aead_decrypt as psa_aead_decrypt_proto;
5155
use generated_ops::psa_aead_encrypt as psa_aead_encrypt_proto;
5256
use generated_ops::psa_asymmetric_decrypt as psa_asymmetric_decrypt_proto;
@@ -207,6 +211,13 @@ impl Convert for ProtobufConverter {
207211
body.bytes(),
208212
psa_raw_key_agreement_proto::Operation
209213
))),
214+
Opcode::AttestKey => Ok(NativeOperation::AttestKey(wire_to_native!(
215+
body.bytes(),
216+
attest_key_proto::Operation
217+
))),
218+
Opcode::PrepareKeyAttestation => Ok(NativeOperation::PrepareKeyAttestation(
219+
wire_to_native!(body.bytes(), prepare_key_attestation_proto::Operation),
220+
)),
210221
}
211222
}
212223

@@ -292,6 +303,13 @@ impl Convert for ProtobufConverter {
292303
NativeOperation::PsaRawKeyAgreement(operation) => Ok(RequestBody::from_bytes(
293304
native_to_wire!(operation, psa_raw_key_agreement_proto::Operation),
294305
)),
306+
NativeOperation::AttestKey(operation) => Ok(RequestBody::from_bytes(native_to_wire!(
307+
operation,
308+
attest_key_proto::Operation
309+
))),
310+
NativeOperation::PrepareKeyAttestation(operation) => Ok(RequestBody::from_bytes(
311+
native_to_wire!(operation, prepare_key_attestation_proto::Operation),
312+
)),
295313
}
296314
}
297315

@@ -399,6 +417,13 @@ impl Convert for ProtobufConverter {
399417
body.bytes(),
400418
psa_raw_key_agreement_proto::Result
401419
))),
420+
Opcode::AttestKey => Ok(NativeResult::AttestKey(wire_to_native!(
421+
body.bytes(),
422+
attest_key_proto::Result
423+
))),
424+
Opcode::PrepareKeyAttestation => Ok(NativeResult::PrepareKeyAttestation(
425+
wire_to_native!(body.bytes(), prepare_key_attestation_proto::Result),
426+
)),
402427
}
403428
}
404429

@@ -499,6 +524,13 @@ impl Convert for ProtobufConverter {
499524
NativeResult::PsaRawKeyAgreement(result) => Ok(ResponseBody::from_bytes(
500525
native_to_wire!(result, psa_raw_key_agreement_proto::Result),
501526
)),
527+
NativeResult::AttestKey(result) => Ok(ResponseBody::from_bytes(native_to_wire!(
528+
result,
529+
attest_key_proto::Result
530+
))),
531+
NativeResult::PrepareKeyAttestation(result) => Ok(ResponseBody::from_bytes(
532+
native_to_wire!(result, prepare_key_attestation_proto::Result),
533+
)),
502534
}
503535
}
504536
}

‎src/requests/mod.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ pub enum Opcode {
137137
ListClients = 0x001B,
138138
/// DeleteClient operation (admin operation)
139139
DeleteClient = 0x001C,
140+
/// AttestKey operation
141+
AttestKey = 0x001E,
142+
/// PrepareKeyAttestation operation
143+
PrepareKeyAttestation = 0x001F,
140144
}
141145

142146
impl Opcode {
@@ -169,7 +173,9 @@ impl Opcode {
169173
| Opcode::PsaAeadDecrypt
170174
| Opcode::PsaCipherEncrypt
171175
| Opcode::PsaCipherDecrypt
172-
| Opcode::PsaRawKeyAgreement => false,
176+
| Opcode::PsaRawKeyAgreement
177+
| Opcode::AttestKey
178+
| Opcode::PrepareKeyAttestation => false,
173179
}
174180
}
175181

@@ -201,7 +207,9 @@ impl Opcode {
201207
| Opcode::PsaAeadDecrypt
202208
| Opcode::PsaCipherEncrypt
203209
| Opcode::PsaCipherDecrypt
204-
| Opcode::PsaRawKeyAgreement => false,
210+
| Opcode::PsaRawKeyAgreement
211+
| Opcode::AttestKey
212+
| Opcode::PrepareKeyAttestation => false,
205213
}
206214
}
207215

0 commit comments

Comments
 (0)
Please sign in to comment.