Skip to content

Commit acb2799

Browse files
src: Get random authvalues locally instead of from the TPM
Currently, the TPM itself is the root of trust for randomness in authvalues used for creating Primary Keys. This is susceptible to physical attacks over the TPM bus. * Get authvalues via the 'getrandom' crate getrandom retrieves random data from the (operating) system sources and assumes "that the system always provides high-quality cryptographically secure random data, ideally backed by hardware entropy sources", so the administrator of the platfrom should take this into account. Note: This change may slow down the tests as accessing random values from the OS instead of the TPM may be slower. Signed-off-by: Tomás González <tomasagustin.gonzalezorlando@arm.com>
1 parent e818ff6 commit acb2799

13 files changed

+112
-91
lines changed

tss-esapi/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ cfg-if = "1.0.0"
3434
strum = { version = "0.25.0", optional = true }
3535
strum_macros = { version = "0.25.0", optional = true }
3636
paste = "1.0.14"
37+
getrandom = "0.2.11"
3738

3839
[dev-dependencies]
3940
env_logger = "0.9.0"

tss-esapi/src/abstraction/transient/mod.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ impl TransientKeyContext {
137137
///
138138
/// # Errors
139139
/// * if the authentication size is larger than 32 a `WrongParamSize` wrapper error is returned
140+
/// * if there is an error when obtaining random numbers from the local machine
140141
pub fn create_key(
141142
&mut self,
142143
key_params: KeyParams,
@@ -147,8 +148,12 @@ impl TransientKeyContext {
147148
}
148149
let key_auth = if auth_size > 0 {
149150
self.set_session_attrs()?;
150-
let random_bytes = self.context.get_random(auth_size)?;
151-
Some(Auth::from_bytes(random_bytes.as_bytes())?)
151+
let mut random_bytes = vec![0u8; auth_size];
152+
getrandom::getrandom(&mut random_bytes).map_err(|_| {
153+
log::error!("Failed to obtain a random authvalue for key creation");
154+
Error::WrapperError(ErrorKind::InternalError)
155+
})?;
156+
Some(Auth::from_bytes(random_bytes.as_slice())?)
152157
} else {
153158
None
154159
};
@@ -630,7 +635,7 @@ impl TransientKeyContextBuilder {
630635
/// Bootstrap the TransientKeyContext.
631636
///
632637
/// The root key is created as a primary key in the provided hierarchy and thus authentication is
633-
/// needed for said hierarchy. The authentication value for the key is generated by the TPM itself,
638+
/// needed for said hierarchy. The authentication value for the key is generated locally in the machine,
634639
/// with a configurable length, and never exposed outside the context.
635640
///
636641
/// # Warning
@@ -643,9 +648,9 @@ impl TransientKeyContextBuilder {
643648
/// * `root_key_auth_size` must be at most 32
644649
///
645650
/// # Errors
646-
/// * errors are returned if any method calls return an error: `Context::get_random`,
647-
/// `Context::start_auth_session`, `Context::create_primary`, `Context::flush_context`,
648-
/// `Context::set_handle_auth`
651+
/// * errors are returned if any method calls return an error: `Context::start_auth_session`
652+
/// `Context::create_primary`, `Context::flush_context`, `Context::set_handle_auth`
653+
/// or if an internal error occurs when getting random numbers from the local machine
649654
/// * if the root key authentication size is given greater than 32 or if the root key size is
650655
/// not 1024, 2048, 3072 or 4096, a `InvalidParam` wrapper error is returned
651656
pub fn build(mut self) -> Result<TransientKeyContext> {
@@ -658,8 +663,12 @@ impl TransientKeyContextBuilder {
658663
let mut context = Context::new(self.tcti_name_conf)?;
659664

660665
let root_key_auth = if self.root_key_auth_size > 0 {
661-
let random = context.get_random(self.root_key_auth_size)?;
662-
Some(Auth::from_bytes(random.as_bytes())?)
666+
let mut random = vec![0u8; self.root_key_auth_size];
667+
getrandom::getrandom(&mut random).map_err(|_| {
668+
log::error!("Failed to obtain a random value for root key authentication");
669+
Error::WrapperError(ErrorKind::InternalError)
670+
})?;
671+
Some(Auth::from_bytes(random.as_slice())?)
663672
} else {
664673
None
665674
};

tss-esapi/src/context/tpm_commands/asymmetric_primitives.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,9 @@ impl Context {
127127
/// # context.tr_sess_set_attributes(session, session_attributes, session_attributes_mask)
128128
/// # .expect("Failed to set attributes on session");
129129
/// # context.set_sessions((Some(session), None, None));
130-
/// # let random_digest = context.get_random(16).unwrap();
131-
/// # let key_auth = Auth::from_bytes(random_digest.as_bytes()).unwrap();
130+
/// # let mut random_digest = vec![0u8; 16];
131+
/// # getrandom::getrandom(&mut random_digest).unwrap();
132+
/// # let key_auth = Auth::from_bytes(random_digest.as_slice()).unwrap();
132133
/// #
133134
/// // Create a key suitable for ECDH key generation
134135
/// let ecc_parms = PublicEccParametersBuilder::new()
@@ -262,8 +263,9 @@ impl Context {
262263
/// # context.tr_sess_set_attributes(session, session_attributes, session_attributes_mask)
263264
/// # .expect("Failed to set attributes on session");
264265
/// # context.set_sessions((Some(session), None, None));
265-
/// # let random_digest = context.get_random(16).unwrap();
266-
/// # let key_auth = Auth::from_bytes(random_digest.as_bytes()).unwrap();
266+
/// # let mut random_digest = vec![0u8; 16];
267+
/// # getrandom::getrandom(&mut random_digest).unwrap();
268+
/// # let key_auth = Auth::from_bytes(random_digest.as_slice()).unwrap();
267269
/// #
268270
/// // Create a key suitable for ECDH key generation
269271
/// let ecc_parms = PublicEccParametersBuilder::new()

tss-esapi/src/context/tpm_commands/context_management.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,9 @@ impl Context {
112112
///
113113
/// // Execute context methods using the session
114114
/// context.execute_with_session(Some(session), |ctx| {
115-
/// let random_digest = ctx.get_random(16)
116-
/// .expect("Call to get_random failed");
117-
/// let key_auth = Auth::from_bytes(random_digest.as_bytes())
118-
/// .expect("Failed to create Auth");
115+
/// let mut random_digest = vec![0u8; 16];
116+
/// getrandom::getrandom(&mut random_digest).expect("Call to getrandom failed");
117+
/// let key_auth = Auth::from_bytes(random_digest.as_slice()).expect("Failed to create Auth");
119118
/// let key_handle = ctx
120119
/// .create_primary(
121120
/// Hierarchy::Owner,

tss-esapi/src/context/tpm_commands/symmetric_primitives.rs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,11 @@ impl Context {
5656
/// # .tr_set_auth(tss_esapi::interface_types::reserved_handles::Hierarchy::Owner.into(), Auth::default())
5757
/// # .expect("Failed to set auth to empty for owner");
5858
/// # // Create primary key auth
59-
/// # let primary_key_auth = Auth::try_from(
60-
/// # context
61-
/// # .get_random(16)
62-
/// # .expect("get_rand call failed")
63-
/// # .as_bytes()
64-
/// # .to_vec(),
59+
/// # let mut random_digest = vec![0u8; 16];
60+
/// # getrandom::getrandom(&mut random_digest).expect("get_rand call failed");
61+
/// # let primary_key_auth = Auth::from_bytes(
62+
/// # random_digest
63+
/// # .as_slice()
6564
/// # )
6665
/// # .expect("Failed to create primary key auth");
6766
/// # // Create primary key
@@ -103,12 +102,11 @@ impl Context {
103102
/// # .build()
104103
/// # .expect("Failed to create public for symmetric key public");
105104
/// # // Create auth for the symmetric key
106-
/// # let symmetric_key_auth = Auth::try_from(
107-
/// # context
108-
/// # .get_random(16)
109-
/// # .expect("get_rand call failed")
110-
/// # .as_bytes()
111-
/// # .to_vec(),
105+
/// # let mut random_digest = vec![0u8; 16];
106+
/// # getrandom::getrandom(&mut random_digest).expect("get_rand call failed");
107+
/// # let symmetric_key_auth = Auth::from_bytes(
108+
/// # random_digest
109+
/// # .as_slice()
112110
/// # )
113111
/// # .expect("Failed to create symmetric key auth");
114112
/// # // Create symmetric key data

tss-esapi/tests/integration_tests/abstraction_tests/transient_key_context_tests.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -502,8 +502,9 @@ fn ctx_migration_test() {
502502
// Create two key contexts using `Context`, one for an RSA keypair,
503503
// one for just the public part of the key
504504
let mut basic_ctx = crate::common::create_ctx_with_session();
505-
let random_digest = basic_ctx.get_random(16).unwrap();
506-
let key_auth = Auth::from_bytes(random_digest.as_bytes()).unwrap();
505+
let mut random_digest = vec![0u8; 16];
506+
getrandom::getrandom(&mut random_digest).unwrap();
507+
let key_auth = Auth::from_bytes(random_digest.as_slice()).unwrap();
507508
let prim_key_handle = basic_ctx
508509
.create_primary(
509510
Hierarchy::Owner,

tss-esapi/tests/integration_tests/context_tests/tpm_commands/asymmetric_primitives_tests.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ mod test_rsa_encrypt_decrypt {
1919
#[test]
2020
fn test_encrypt_decrypt() {
2121
let mut context = create_ctx_with_session();
22-
let random_digest = context.get_random(16).unwrap();
23-
let key_auth = Auth::from_bytes(random_digest.as_bytes()).unwrap();
22+
let mut random_digest = vec![0u8; 16];
23+
getrandom::getrandom(&mut random_digest).unwrap();
24+
let key_auth = Auth::from_bytes(random_digest.as_slice()).unwrap();
2425

2526
let key_handle = context
2627
.create_primary(
@@ -59,8 +60,9 @@ mod test_rsa_encrypt_decrypt {
5960
#[test]
6061
fn test_ecdh() {
6162
let mut context = create_ctx_with_session();
62-
let random_digest = context.get_random(16).unwrap();
63-
let key_auth = Auth::from_bytes(random_digest.as_bytes()).unwrap();
63+
let mut random_digest = vec![0u8; 16];
64+
getrandom::getrandom(&mut random_digest).unwrap();
65+
let key_auth = Auth::from_bytes(random_digest.as_slice()).unwrap();
6466

6567
let ecc_parms = PublicEccParametersBuilder::new()
6668
.with_ecc_scheme(EccScheme::EcDh(HashScheme::new(HashingAlgorithm::Sha256)))

tss-esapi/tests/integration_tests/context_tests/tpm_commands/context_management_tests.rs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ mod test_ctx_save {
77
#[test]
88
fn test_ctx_save() {
99
let mut context = create_ctx_with_session();
10-
let random_digest = context.get_random(16).unwrap();
11-
let key_auth = Auth::from_bytes(random_digest.as_bytes()).unwrap();
10+
let mut random_digest = vec![0u8; 16];
11+
getrandom::getrandom(&mut random_digest).unwrap();
12+
let key_auth = Auth::from_bytes(random_digest.as_slice()).unwrap();
1213

1314
let key_handle = context
1415
.create_primary(
@@ -27,8 +28,9 @@ mod test_ctx_save {
2728
#[test]
2829
fn test_ctx_save_leaf() {
2930
let mut context = create_ctx_with_session();
30-
let random_digest = context.get_random(16).unwrap();
31-
let key_auth = Auth::from_bytes(random_digest.as_bytes()).unwrap();
31+
let mut random_digest = vec![0u8; 16];
32+
getrandom::getrandom(&mut random_digest).unwrap();
33+
let key_auth = Auth::from_bytes(random_digest.as_slice()).unwrap();
3234

3335
let prim_key_handle = context
3436
.create_primary(
@@ -70,13 +72,14 @@ mod test_ctx_load {
7072
#[test]
7173
fn test_ctx_load() {
7274
let mut context = create_ctx_with_session();
73-
let key_auth = context.get_random(16).unwrap();
75+
let mut random_digest = vec![0u8; 16];
76+
getrandom::getrandom(&mut random_digest).unwrap();
7477

7578
let prim_key_handle = context
7679
.create_primary(
7780
Hierarchy::Owner,
7881
decryption_key_pub(),
79-
Some(Auth::from_bytes(key_auth.as_bytes()).unwrap()),
82+
Some(Auth::from_bytes(random_digest.as_slice()).unwrap()),
8083
None,
8184
None,
8285
None,
@@ -88,7 +91,7 @@ mod test_ctx_load {
8891
.create(
8992
prim_key_handle,
9093
signing_key_pub(),
91-
Some(Auth::from_bytes(key_auth.as_bytes()).unwrap()),
94+
Some(Auth::from_bytes(random_digest.as_slice()).unwrap()),
9295
None,
9396
None,
9497
None,
@@ -112,8 +115,9 @@ mod test_flush_context {
112115
#[test]
113116
fn test_flush_ctx() {
114117
let mut context = create_ctx_with_session();
115-
let random_digest = context.get_random(16).unwrap();
116-
let key_auth = Auth::from_bytes(random_digest.as_bytes()).unwrap();
118+
let mut random_digest = vec![0u8; 16];
119+
getrandom::getrandom(&mut random_digest).unwrap();
120+
let key_auth = Auth::from_bytes(random_digest.as_slice()).unwrap();
117121

118122
let key_handle = context
119123
.create_primary(
@@ -133,8 +137,9 @@ mod test_flush_context {
133137
#[test]
134138
fn test_flush_parent_ctx() {
135139
let mut context = create_ctx_with_session();
136-
let random_digest = context.get_random(16).unwrap();
137-
let key_auth = Auth::from_bytes(random_digest.as_bytes()).unwrap();
140+
let mut random_digest = vec![0u8; 16];
141+
getrandom::getrandom(&mut random_digest).unwrap();
142+
let key_auth = Auth::from_bytes(random_digest.as_slice()).unwrap();
138143

139144
let prim_key_handle = context
140145
.create_primary(

tss-esapi/tests/integration_tests/context_tests/tpm_commands/enhanced_authorization_ea_commands_tests.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -536,8 +536,9 @@ mod test_policy_authorize {
536536
#[test]
537537
fn test_policy_authorize() {
538538
let mut context = create_ctx_with_session();
539-
let random_digest = context.get_random(16).unwrap();
540-
let key_auth = Auth::from_bytes(random_digest.as_bytes()).unwrap();
539+
let mut random_digest = vec![0u8; 16];
540+
getrandom::getrandom(&mut random_digest).unwrap();
541+
let key_auth = Auth::from_bytes(random_digest.as_slice()).unwrap();
541542

542543
let key_handle = context
543544
.create_primary(

tss-esapi/tests/integration_tests/context_tests/tpm_commands/hierarchy_commands_tests.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ mod test_create_primary {
99
#[test]
1010
fn test_create_primary() {
1111
let mut context = create_ctx_with_session();
12-
let random_digest = context.get_random(16).unwrap();
13-
let key_auth = Auth::from_bytes(random_digest.as_bytes()).unwrap();
12+
let mut random_digest = vec![0u8; 16];
13+
getrandom::getrandom(&mut random_digest).unwrap();
14+
let key_auth = Auth::from_bytes(random_digest.as_slice()).unwrap();
1415

1516
let key_handle = context
1617
.create_primary(
@@ -93,8 +94,9 @@ mod test_change_auth {
9394
)
9495
.unwrap();
9596

96-
let random_digest = context.get_random(16).unwrap();
97-
let new_key_auth = Auth::from_bytes(random_digest.as_bytes()).unwrap();
97+
let mut random_digest = vec![0u8; 16];
98+
getrandom::getrandom(&mut random_digest).unwrap();
99+
let new_key_auth = Auth::from_bytes(random_digest.as_slice()).unwrap();
98100

99101
let new_private = context
100102
.object_change_auth(loaded_key.into(), prim_key_handle.into(), new_key_auth)
@@ -108,8 +110,9 @@ mod test_change_auth {
108110
fn test_hierarchy_change_auth() {
109111
let mut context = create_ctx_with_session();
110112

111-
let random_digest = context.get_random(16).unwrap();
112-
let new_auth = Auth::from_bytes(random_digest.as_bytes()).unwrap();
113+
let mut random_digest = vec![0u8; 16];
114+
getrandom::getrandom(&mut random_digest).unwrap();
115+
let new_auth = Auth::from_bytes(random_digest.as_slice()).unwrap();
113116

114117
// NOTE: If this test failed on your system, you are probably running it against a
115118
// real (hardware) TPM or one that is provisioned. This hierarchy is supposed to be

0 commit comments

Comments
 (0)