Skip to content

Commit f18602b

Browse files
author
Nicolas Pernoud
committed
example: file symmetric encryption en decryption
Signed-off-by: Nicolas Pernoud <nicolas.pernoud@stormshield.eu>
1 parent d68a13a commit f18602b

File tree

2 files changed

+218
-0
lines changed

2 files changed

+218
-0
lines changed
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
use core::str;
2+
use std::fs;
3+
use std::convert::TryFrom;
4+
use tss_esapi::{
5+
attributes::ObjectAttributesBuilder,
6+
interface_types::{
7+
algorithm::{HashingAlgorithm, PublicAlgorithm, SymmetricMode}, reserved_handles::Hierarchy,
8+
},
9+
structures::{
10+
CreatePrimaryKeyResult, Digest, InitialValue, MaxBuffer, PublicBuilder,
11+
SymmetricCipherParameters, SymmetricDefinitionObject,
12+
},
13+
Context, TctiNameConf,
14+
};
15+
16+
fn main() {
17+
// Create a new TPM context. This reads from the environment variable `TPM2TOOLS_TCTI` or `TCTI`
18+
//
19+
// It's recommended you use `TCTI=device:/dev/tpmrm0` for the linux kernel
20+
// tpm resource manager.
21+
let mut context = Context::new(
22+
TctiNameConf::from_environment_variable()
23+
.expect("Failed to get TCTI / TPM2TOOLS_TCTI from environment. Try `export TCTI=device:/dev/tpmrm0`"),
24+
)
25+
.expect("Failed to create Context");
26+
27+
// This example won't go over the process to create a new parent. For more detail see `examples/hmac.rs`.
28+
let primary = create_primary(&mut context);
29+
30+
// Create the AES key. This key exists under the primary key in it's hierarchy
31+
// and can only be used if the same primary key is recreated from the parameters
32+
// defined above.
33+
let object_attributes = ObjectAttributesBuilder::new()
34+
.with_fixed_tpm(true)
35+
.with_fixed_parent(true)
36+
.with_st_clear(false)
37+
.with_sensitive_data_origin(true)
38+
.with_user_with_auth(true)
39+
.with_sign_encrypt(true)
40+
.with_decrypt(true)
41+
.build()
42+
.expect("Failed to build object attributes");
43+
44+
let key_pub = PublicBuilder::new()
45+
// This key is a AES key
46+
.with_public_algorithm(PublicAlgorithm::SymCipher)
47+
.with_name_hashing_algorithm(HashingAlgorithm::Sha256)
48+
.with_symmetric_cipher_parameters(SymmetricCipherParameters::new(
49+
SymmetricDefinitionObject::AES_128_CFB,
50+
))
51+
.with_object_attributes(object_attributes)
52+
.with_symmetric_cipher_unique_identifier(Digest::default())
53+
.build()
54+
.unwrap();
55+
56+
let (private, public) = context
57+
.execute_with_nullauth_session(|ctx| {
58+
// Create the AES key given our primary key as it's parent. This returns the private
59+
// and public portions of the key. It's *important* to note that the private component
60+
// is *encrypted* by a key associated with the primary key. It is not plaintext or
61+
// leaked in this step.
62+
ctx.create(primary.key_handle, key_pub, None, None, None, None)
63+
.map(|key| (key.out_private, key.out_public))
64+
})
65+
.unwrap();
66+
67+
// Once the key is created, we have it's parameters in the private and public values.
68+
// We now need to load it into the tpm so that it can be used.
69+
//
70+
// The enc_private and public values can be serialised and persisted - that way they can
71+
// be reloaded for future use.
72+
73+
// We load the data from a file system file, it can be somewhat large (like a certificate), larger than MaxBuffer::MAX_SIZE
74+
let initial_data = fs::read("tss-esapi/examples/symmetric_file_encrypt_decrypt_example.txt").expect("could not open data file");
75+
76+
// We create an initialisation vector, since it is needed for decryption, it should be persisted in a real world use case
77+
let iv = context
78+
.execute_with_nullauth_session(|ctx| {
79+
InitialValue::from_bytes(
80+
ctx.get_random(16)
81+
.expect("could not get random bytes for initialisation vector")
82+
.as_bytes(),
83+
)
84+
})
85+
.expect("could not create iv from random bytes");
86+
87+
// We encrypt the data
88+
let encrypted_data = context
89+
.execute_with_nullauth_session(|ctx| {
90+
let mut encrypted_data = Vec::new();
91+
let handle = ctx
92+
.load(primary.key_handle, private.clone(), public.clone())
93+
.expect("could not load child key");
94+
95+
let mut chunk_iv = iv.clone();
96+
97+
// This file is larger than the MaxBuffer::MAX_SIZE, so we need to chunk it
98+
// The iv must be different for every chunk, the encrypt_decrypt_2 function conveniently provide a new one at each iteration
99+
for chunk in initial_data.chunks(MaxBuffer::MAX_SIZE) {
100+
let data = MaxBuffer::try_from(Vec::from(chunk))
101+
.expect("failed to create data from file buffer chunk");
102+
let (enc_data, chunk_iv_out) = ctx.encrypt_decrypt_2(
103+
handle, // Handle to a symmetric key
104+
false, // false, indicates that the data should be encrypted
105+
SymmetricMode::Cfb, // The symmetric mode of the encryption
106+
data, // The data that is to be encrypted
107+
chunk_iv, // Initial value needed by the algorithm
108+
)?;
109+
chunk_iv = chunk_iv_out;
110+
encrypted_data.push(enc_data);
111+
}
112+
Ok::<Vec<MaxBuffer>, tss_esapi::Error>(encrypted_data)
113+
})
114+
.expect("Call to encrypt_decrypt_2 failed when encrypting data");
115+
let encrypted_data = encrypted_data
116+
.iter()
117+
.map(|e| e.as_bytes())
118+
.collect::<Vec<_>>()
119+
.concat();
120+
121+
// Decrypting is exactly the opposite, with the same first iv
122+
let decrypted_data = context
123+
.execute_with_nullauth_session(|ctx| {
124+
let mut decrypted_data = Vec::new();
125+
let handle = ctx
126+
.load(primary.key_handle, private.clone(), public.clone())
127+
.expect("could not load child key");
128+
129+
let mut chunk_iv = iv;
130+
131+
for chunk in encrypted_data.chunks(MaxBuffer::MAX_SIZE) {
132+
let data = MaxBuffer::try_from(Vec::from(chunk))
133+
.expect("failed to create data from encrypted data chunk");
134+
let (enc_data, chunk_iv_out) = ctx.encrypt_decrypt_2(
135+
handle, // Handle to a symmetric key
136+
true, // true, indicates that the data should be decrypted
137+
SymmetricMode::Cfb, // The symmetric mode of the encryption
138+
data, // The data that is to be encrypted
139+
chunk_iv, // Initial value needed by the algorithm
140+
)?;
141+
chunk_iv = chunk_iv_out;
142+
decrypted_data.push(enc_data);
143+
} //
144+
Ok::<Vec<MaxBuffer>, tss_esapi::Error>(decrypted_data)
145+
})
146+
.expect("Call to encrypt_decrypt_2 failed when encrypting data");
147+
let decrypted_data = decrypted_data
148+
.iter()
149+
.map(|e| e.as_bytes())
150+
.collect::<Vec<_>>()
151+
.concat();
152+
153+
println!(
154+
"=== Initial data ===\n\n{}\n\n\n\n",
155+
str::from_utf8(&initial_data).unwrap()
156+
);
157+
print!("");
158+
println!(
159+
"=== Decrypted data ===\n\n{}",
160+
str::from_utf8(&decrypted_data).unwrap()
161+
);
162+
// They are the same!
163+
assert_eq!(initial_data, decrypted_data);
164+
}
165+
166+
fn create_primary(context: &mut Context) -> CreatePrimaryKeyResult {
167+
// Create the primary key. A primary key is the "root" of a collection of objects.
168+
// These other objects are encrypted by the primary key allowing them to persist
169+
// over a reboot and reloads.
170+
//
171+
// A primary key is derived from a seed, and provided that the same inputs are given
172+
// the same primary key will be derived in the tpm. This means that you do not need
173+
// to store or save the details of this key - only the parameters of how it was created.
174+
let object_attributes = ObjectAttributesBuilder::new()
175+
// Indicate the key can only exist within this tpm and can not be exported.
176+
.with_fixed_tpm(true)
177+
// The primary key and it's descendent keys can't be moved to other primary
178+
// keys.
179+
.with_fixed_parent(true)
180+
// The primary key will persist over suspend and resume of the system.
181+
.with_st_clear(false)
182+
// The primary key was generated entirely inside the TPM - only this TPM
183+
// knows it's content.
184+
.with_sensitive_data_origin(true)
185+
// This key requires "authentication" to the TPM to access - this can be
186+
// an HMAC or password session. HMAC sessions are used by default with
187+
// the "execute_with_nullauth_session" function.
188+
.with_user_with_auth(true)
189+
// This key has the ability to decrypt
190+
.with_decrypt(true)
191+
// This key may only be used to encrypt or sign objects that are within
192+
// the TPM - it can not encrypt or sign external data.
193+
.with_restricted(true)
194+
.build()
195+
.expect("Failed to build object attributes");
196+
197+
let primary_pub = PublicBuilder::new()
198+
// This key is a symmetric key.
199+
.with_public_algorithm(PublicAlgorithm::SymCipher)
200+
.with_name_hashing_algorithm(HashingAlgorithm::Sha256)
201+
.with_object_attributes(object_attributes)
202+
.with_symmetric_cipher_parameters(SymmetricCipherParameters::new(
203+
SymmetricDefinitionObject::AES_128_CFB,
204+
))
205+
.with_symmetric_cipher_unique_identifier(Digest::default())
206+
.build()
207+
.unwrap();
208+
209+
context
210+
.execute_with_nullauth_session(|ctx| {
211+
// Create the key under the "owner" hierarchy. Other hierarchies are platform
212+
// which is for boot services, null which is ephemeral and resets after a reboot,
213+
// and endorsement which allows key certification by the TPM manufacturer.
214+
ctx.create_primary(Hierarchy::Owner, primary_pub, None, None, None, None)
215+
})
216+
.unwrap()
217+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lorem ipsum dolor sit amet consectetur adipiscing elit in lacinia egestas, eget cubilia laoreet vel iaculis urna gravida elementum himenaeos. Mattis mus nullam fames malesuada scelerisque quisque nec enim nisl inceptos, vehicula dapibus cursus nunc convallis diam lacinia proin. Accumsan mattis felis varius ligula, sagittis dignissim potenti rhoncus lectus, purus sed arcu. Arcu augue eleifend litora ultrices senectus laoreet fusce, suspendisse pharetra pulvinar risus penatibus odio eu, nam nulla platea interdum erat aptent. Dis euismod tincidunt tortor luctus morbi netus sagittis consequat, sollicitudin aptent volutpat fermentum condimentum ridiculus risus ullamcorper turpis, class penatibus in vel diam pretium est. Varius tempus fames habitasse et nibh turpis nam lobortis faucibus, eget dapibus odio nunc praesent nullam interdum. Rutrum mollis iaculis netus elementum potenti tristique phasellus, porta sociis integer tortor sodales neque, quis vestibulum varius morbi viverra himenaeos. Habitasse inceptos cursus elementum mi dictumst blandit nam, habitant montes quis praesent fames potenti sem, consequat tellus sollicitudin vivamus mollis dui. Nostra felis ullamcorper sociosqu integer penatibus luctus lacus bibendum suspendisse dis, eu a ridiculus sapien litora hendrerit blandit fusce fringilla viverra, suscipit habitasse odio aliquet mus congue quam conubia himenaeos. Sem porttitor vehicula consequat pretium fames ullamcorper posuere rutrum, vulputate cursus phasellus magnis accumsan diam. Iaculis hendrerit sodales sagittis in maecenas vel tristique, ultrices augue malesuada accumsan etiam pulvinar, ligula mauris convallis turpis natoque imperdiet pellentesque, diam torquent tempus commodo sapien. Consequat habitasse porta ut nascetur augue urna, eu tortor placerat eleifend proin, egestas natoque tincidunt feugiat morbi. Lacus faucibus viverra cubilia nascetur dictum a potenti commodo facilisi, fames mauris posuere erat mus senectus est placerat ornare mollis, vitae sociosqu suscipit luctus montes sem maecenas vel. Lacinia sollicitudin lobortis duis nisl posuere gravida tristique tempus volutpat netus class parturient arcu, velit torquent in cursus etiam ultricies eu sem lacus habitasse rutrum morbi. Molestie facilisis sodales lobortis et ultrices cum nam curabitur, odio bibendum nec platea placerat natoque tempor, habitant morbi montes tristique nullam massa cursus. Natoque quam pharetra fames iaculis rutrum leo metus dis dictum, sollicitudin per tempus senectus cum magna nisl scelerisque accumsan, justo ligula massa mattis primis est nullam congue. Pulvinar arcu tempor fermentum diam nisl ridiculus molestie accumsan nostra volutpat fringilla placerat, venenatis dapibus penatibus aliquam lacinia quam risus sagittis neque velit ac. Turpis inceptos est morbi primis vulputate euismod in vivamus iaculis, suscipit platea curae rhoncus montes aliquet sapien nostra, quisque vitae dignissim rutrum id gravida feugiat pretium. Integer arcu litora facilisis hac accumsan nisi suspendisse, aenean suscipit vel curabitur nostra. Molestie conubia venenatis nullam placerat mollis vulputate egestas, sodales tellus justo commodo metus suspendisse turpis, volutpat dignissim laoreet ante est sociis. Mauris rutrum suspendisse lacinia massa lectus natoque arcu nostra est sem mollis rhoncus per, fermentum curae tristique eros suscipit justo fames nec ligula himenaeos velit. Euismod felis platea velit cum rhoncus aptent, mollis aliquam penatibus non nisl per pellentesque, eget tortor magnis at varius. Ut magnis suspendisse turpis montes sociis aptent gravida arcu, mus vehicula eu facilisi molestie hendrerit hac dictumst, quam id ultrices in parturient scelerisque dignissim. Elementum primis porta nibh ullamcorper placerat ad dapibus mauris velit, nascetur cursus senectus consequat platea sagittis inceptos orci, taciti fusce parturient feugiat sapien imperdiet leo vitae. Nam tellus suscipit viverra lacus ac maecenas molestie quisque, ut natoque vel feugiat magna nulla bibendum, mi purus euismod hac phasellus ad arcu. Scelerisque facilisi a eros enim et purus, malesuada pretium mauris interdum natoque, ut dignissim magnis senectus ac. Facilisis tempus viverra penatibus mi rhoncus ut montes semper duis, posuere laoreet ultrices luctus molestie cras ac neque aptent, metus eu ridiculus urna nisl arcu vehicula fermentum. Aenean class eget sociis ridiculus accumsan, porta fringilla facilisi netus cum, eu sed imperdiet vel. Parturient odio proin integer lobortis primis lectus magnis sapien dictumst per sociis, condimentum euismod eros cras nascetur vel facilisi leo urna. Natoque fusce eleifend integer porttitor felis fermentum lacus iaculis dignissim, erat sapien malesuada primis pharetra etiam potenti neque, facilisi luctus tempor accumsan faucibus rutrum tristique dis. Nulla egestas nisl risus condimentum scelerisque diam sed mollis cursus, netus libero facilisi proin semper phasellus varius nullam nam parturient, donec est sociosqu acc.

0 commit comments

Comments
 (0)