Skip to content

Commit 55774ad

Browse files
committed
WIP: Create credentials
Signed-off-by: Arthur Gautier <[email protected]>
1 parent 7e73a1e commit 55774ad

File tree

7 files changed

+490
-1
lines changed

7 files changed

+490
-1
lines changed

Cargo.toml

+5
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,8 @@ p192 = { git = "https://github.com/RustCrypto/elliptic-curves.git" }
77
p224 = { git = "https://github.com/RustCrypto/elliptic-curves.git" }
88
sm2 = { git = "https://github.com/RustCrypto/elliptic-curves.git" }
99

10+
# https://github.com/RustCrypto/KDFs/pull/108
11+
kbkdf = { git = "https://github.com/TheBestTvarynka/KDFs.git", branch = "feat/kbkdf" }
12+
concat-kdf = { git = "https://github.com/RustCrypto/KDFs.git" }
13+
14+
cfb-mode = { git = "https://github.com/RustCrypto/block-modes.git" }

tss-esapi/Cargo.toml

+9-1
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@ regex = "1.3.9"
3535
zeroize = { version = "1.5.7", features = ["zeroize_derive"] }
3636
tss-esapi-sys = { path = "../tss-esapi-sys", version = "0.5.0" }
3737
x509-cert = { version = "0.3.0-pre.0", optional = true }
38+
cfb-mode = { version = "0.9.0-pre", optional = true }
3839
ecdsa = { version = "0.17.0-pre.9", features = ["der", "hazmat", "arithmetic", "verifying"], optional = true }
3940
elliptic-curve = { version = "0.14.0-rc.1", optional = true, features = ["alloc", "pkcs8"] }
41+
hmac = { version = "0.13.0-pre.4", optional = true }
4042
p192 = { version = "0.14.0-pre", optional = true }
4143
p224 = { version = "0.14.0-pre", optional = true }
4244
p256 = { version = "0.14.0-pre.2", optional = true }
@@ -48,16 +50,21 @@ sha2 = { version = "0.11.0-pre.4", optional = true }
4850
sha3 = { version = "0.11.0-pre.4", optional = true }
4951
sm2 = { version = "0.14.0-pre", optional = true }
5052
sm3 = { version = "0.5.0-pre.4", optional = true }
53+
kbkdf = { version = "0.1.0" }
54+
concat-kdf = { version = "0.2.0-pre" }
5155
digest = "0.11.0-pre.9"
5256
signature = { version = "2.3.0-pre.4", features = ["std"], optional = true}
5357
cfg-if = "1.0.0"
5458
strum = { version = "0.26.3", optional = true }
5559
strum_macros = { version = "0.26.4", optional = true }
5660
paste = "1.0.14"
5761
getrandom = "0.2.11"
62+
rand = "0.8"
63+
aes = "0.9.0-pre.2"
5864

5965
[dev-dependencies]
6066
env_logger = "0.11.5"
67+
hex-literal = "0.4.1"
6168
serde_json = "^1.0.108"
6269
sha2 = { version = "0.11.0-pre.4", features = ["oid"] }
6370
tss-esapi = { path = ".", features = [
@@ -66,6 +73,7 @@ tss-esapi = { path = ".", features = [
6673
"abstraction",
6774
"rustcrypto-full",
6875
] }
76+
p256 = { version = "0.14.0-pre.2", features = ["ecdh"] }
6977
x509-cert = { version = "0.3.0-pre.0", features = ["builder"] }
7078

7179
[build-dependencies]
@@ -77,6 +85,6 @@ generate-bindings = ["tss-esapi-sys/generate-bindings"]
7785
abstraction = ["rustcrypto"]
7886
integration-tests = ["strum", "strum_macros"]
7987

80-
rustcrypto = ["ecdsa", "elliptic-curve", "signature", "x509-cert"]
88+
rustcrypto = ["cfb-mode", "ecdsa", "elliptic-curve", "hmac", "signature", "x509-cert"]
8189
rustcrypto-full = ["rustcrypto", "p192", "p224", "p256", "p384", "p521", "rsa", "sha1", "sha2", "sha3", "sm2", "sm3"]
8290

tss-esapi/src/utils/credential.rs

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// Copyright 2019 Contributors to the Parsec project.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
use aes::cipher::AsyncStreamCipher;
5+
use core::{marker::PhantomData, ops::Add};
6+
use digest::{
7+
array::ArraySize,
8+
consts::{B1, U8},
9+
crypto_common::{Iv, KeyIvInit, KeySizeUser},
10+
typenum::operator_aliases::{Add1, Sum},
11+
KeyInit, Mac, OutputSizeUser,
12+
};
13+
use ecdsa::elliptic_curve::{
14+
ecdh::{EphemeralSecret, SharedSecret},
15+
sec1::{FromEncodedPoint, ModulusSize, ToEncodedPoint},
16+
AffinePoint, Curve, CurveArithmetic, FieldBytesSize, PublicKey,
17+
};
18+
use hmac::Hmac;
19+
use rand::thread_rng;
20+
use sha2::Sha256;
21+
22+
use crate::{
23+
structures::{EncryptedSecret, IdObject, Name},
24+
utils::kdf::{self},
25+
};
26+
27+
// TpmHmacKey intends to code for the key expected for hmac
28+
// in the KDFa derivations. There are no standard sizes for hmac keys really,
29+
// upstream RustCrypto considers it to be BlockSize, but TPM specification
30+
// has a different opinion on the matter, and expect the key to the output
31+
// bit size of the hash algorithm used.
32+
//
33+
// See https://trustedcomputinggroup.org/wp-content/uploads/TPM-2.0-1.83-Part-1-Architecture.pdf#page=202
34+
// section 24.5 HMAC:
35+
// bits the number of bits in the digest produced by ekNameAlg
36+
struct TpmHmac<H>(PhantomData<H>);
37+
38+
impl<H> KeySizeUser for TpmHmac<H>
39+
where
40+
H: OutputSizeUser,
41+
{
42+
type KeySize = H::OutputSize;
43+
}
44+
45+
pub fn make_credential_ecc<C>(
46+
ek_public: PublicKey<C>,
47+
secret: &[u8],
48+
key_name: Name,
49+
) -> (IdObject, EncryptedSecret)
50+
where
51+
C: Curve + CurveArithmetic,
52+
53+
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
54+
FieldBytesSize<C>: ModulusSize,
55+
56+
<FieldBytesSize<C> as Add>::Output: Add<FieldBytesSize<C>>,
57+
Sum<FieldBytesSize<C>, FieldBytesSize<C>>: ArraySize,
58+
Sum<FieldBytesSize<C>, FieldBytesSize<C>>: Add<U8>,
59+
Sum<Sum<FieldBytesSize<C>, FieldBytesSize<C>>, U8>: Add<B1>,
60+
Add1<Sum<Sum<FieldBytesSize<C>, FieldBytesSize<C>>, U8>>: ArraySize,
61+
{
62+
let mut rng = thread_rng();
63+
64+
let local = EphemeralSecret::<C>::random(&mut rng);
65+
66+
let ecdh_secret: SharedSecret<C> = local.diffie_hellman(&ek_public);
67+
68+
type HmacSha256 = Hmac<Sha256>;
69+
70+
let seed = kdf::kdfe::<kdf::Identity, Sha256, C, aes::Aes256>(
71+
&ecdh_secret,
72+
&local.public_key(),
73+
&ek_public,
74+
);
75+
drop(ecdh_secret);
76+
77+
// The local ECDH pair is used as "encrypted seed"
78+
let encrypted_seed = {
79+
let mut out = vec![];
80+
out.extend_from_slice(&32u16.to_be_bytes()[..]);
81+
out.extend_from_slice(&local.public_key().to_encoded_point(false).x().unwrap());
82+
out.extend_from_slice(&32u16.to_be_bytes()[..]);
83+
out.extend_from_slice(&local.public_key().to_encoded_point(false).y().unwrap());
84+
out
85+
};
86+
87+
let mut sensitive_data = {
88+
let mut out = vec![];
89+
out.extend_from_slice(&u16::try_from(secret.len()).unwrap().to_be_bytes()[..]);
90+
out.extend_from_slice(secret);
91+
out
92+
};
93+
94+
let sym_key = kdf::kdfa::<Sha256, kdf::Storage, aes::Aes128>(&seed, key_name.value(), &[]);
95+
let hmac_key = kdf::kdfa::<Sha256, kdf::Integrity, TpmHmac<Sha256>>(&seed, &[], &[]);
96+
97+
type Aes128CfbEnc = cfb_mode::Encryptor<aes::Aes128>;
98+
let iv: Iv<Aes128CfbEnc> = Default::default();
99+
100+
Aes128CfbEnc::new(&sym_key.into(), &iv.into()).encrypt(&mut sensitive_data);
101+
102+
let mut hmac = HmacSha256::new_from_slice(&hmac_key).unwrap();
103+
hmac.update(&sensitive_data);
104+
hmac.update(key_name.value());
105+
let hmac = hmac.finalize();
106+
107+
let mut out = vec![];
108+
out.extend_from_slice(
109+
&u16::try_from(hmac.into_bytes().len())
110+
.unwrap()
111+
.to_be_bytes()[..],
112+
);
113+
out.extend_from_slice(&hmac.into_bytes());
114+
out.extend_from_slice(&sensitive_data);
115+
116+
(
117+
IdObject::from_bytes(&out).unwrap(),
118+
EncryptedSecret::from_bytes(&encrypted_seed).unwrap(),
119+
)
120+
}

0 commit comments

Comments
 (0)