1use crate::{TpmCryptoError, TpmExternalKey, TpmHash};
7use openssl::{
8 bn::BigNum,
9 hash::MessageDigest,
10 md::Md,
11 pkey::{PKey, Private},
12 pkey_ctx::PkeyCtx,
13 rand::rand_bytes,
14 rsa::{Padding, Rsa},
15};
16use rand::{CryptoRng, RngCore};
17use tpm2_protocol::data::{
18 Tpm2bDigest, Tpm2bEncryptedSecret, Tpm2bPublicKeyRsa, TpmAlgId, TpmaObject, TpmsRsaParms,
19 TpmsSchemeHash, TpmtPublic, TpmtRsaScheme, TpmtSymDefObject, TpmuAsymScheme, TpmuPublicId,
20 TpmuPublicParms,
21};
22
23#[derive(Debug, Clone)]
25pub struct TpmRsaExternalKey {
26 pub n: Tpm2bPublicKeyRsa,
27 pub e: u32,
28 pub key_bits: u16,
29}
30
31impl TryFrom<&TpmtPublic> for TpmRsaExternalKey {
32 type Error = TpmCryptoError;
33
34 fn try_from(public: &TpmtPublic) -> Result<Self, Self::Error> {
35 if public.object_type != TpmAlgId::Rsa {
36 return Err(TpmCryptoError::InvalidRsaParameters);
37 }
38
39 let params = match &public.parameters {
40 TpmuPublicParms::Rsa(params) => Ok(params),
41 _ => Err(TpmCryptoError::InvalidRsaParameters),
42 }?;
43
44 let n = match &public.unique {
45 TpmuPublicId::Rsa(n) => Ok(*n),
46 _ => Err(TpmCryptoError::InvalidRsaParameters),
47 }?;
48
49 let e = if params.exponent == 0 {
50 65537
51 } else {
52 params.exponent
53 };
54
55 Ok(Self {
56 n,
57 e,
58 key_bits: params.key_bits,
59 })
60 }
61}
62
63impl TryFrom<&PKey<Private>> for TpmRsaExternalKey {
64 type Error = TpmCryptoError;
65
66 fn try_from(pkey: &PKey<Private>) -> Result<Self, Self::Error> {
67 let rsa = pkey
68 .rsa()
69 .map_err(|_| TpmCryptoError::InvalidRsaParameters)?;
70 let n = Tpm2bPublicKeyRsa::try_from(rsa.n().to_vec().as_slice())
71 .map_err(|_| TpmCryptoError::InvalidRsaParameters)?;
72
73 let e_bn = rsa.e();
74 if e_bn.is_negative() || e_bn.num_bits() > 32 {
75 return Err(TpmCryptoError::InvalidRsaParameters);
76 }
77 let e_bytes = e_bn.to_vec();
78 let mut e_buf = [0u8; 4];
79 e_buf[4 - e_bytes.len()..].copy_from_slice(&e_bytes);
80 let e = u32::from_be_bytes(e_buf);
81
82 let key_bits =
83 u16::try_from(rsa.size() * 8).map_err(|_| TpmCryptoError::InvalidRsaParameters)?;
84
85 Ok(Self { n, e, key_bits })
86 }
87}
88
89impl TpmExternalKey for TpmRsaExternalKey {
90 fn from_der(bytes: &[u8]) -> Result<(Self, Vec<u8>), TpmCryptoError> {
91 let pkey =
92 PKey::private_key_from_der(bytes).map_err(|_| TpmCryptoError::OperationFailed)?;
93 let public_key = TpmRsaExternalKey::try_from(&pkey)?;
94 let rsa = pkey
95 .rsa()
96 .map_err(|_| TpmCryptoError::InvalidRsaParameters)?;
97 let sensitive = rsa.p().ok_or(TpmCryptoError::OperationFailed)?.to_vec();
98 Ok((public_key, sensitive))
99 }
100
101 fn to_public(
102 &self,
103 hash_alg: TpmAlgId,
104 object_attributes: TpmaObject,
105 symmetric: TpmtSymDefObject,
106 ) -> TpmtPublic {
107 TpmtPublic {
108 object_type: TpmAlgId::Rsa,
109 name_alg: hash_alg,
110 object_attributes,
111 auth_policy: Tpm2bDigest::default(),
112 parameters: TpmuPublicParms::Rsa(TpmsRsaParms {
113 symmetric,
114 scheme: TpmtRsaScheme {
115 scheme: TpmAlgId::Oaep,
116 details: TpmuAsymScheme::Hash(TpmsSchemeHash { hash_alg }),
117 },
118 key_bits: self.key_bits,
119 exponent: if self.e == 65537 { 0 } else { self.e },
120 }),
121 unique: TpmuPublicId::Rsa(self.n),
122 }
123 }
124
125 fn to_seed(
126 &self,
127 name_alg: TpmHash,
128 _rng: &mut (impl RngCore + CryptoRng),
129 ) -> Result<(Vec<u8>, Tpm2bEncryptedSecret), TpmCryptoError> {
130 let seed_size = name_alg.size();
131 let mut seed = vec![0u8; seed_size];
132 rand_bytes(&mut seed).map_err(|_| TpmCryptoError::OperationFailed)?;
133
134 let encrypted_seed_bytes = self.oaep(name_alg, &seed)?;
135
136 let encrypted_seed = Tpm2bEncryptedSecret::try_from(encrypted_seed_bytes.as_slice())
137 .map_err(|_| TpmCryptoError::OutOfMemory)?;
138
139 Ok((seed, encrypted_seed))
140 }
141}
142
143impl TpmRsaExternalKey {
144 fn oaep(&self, name_alg: TpmHash, seed: &[u8]) -> Result<Vec<u8>, TpmCryptoError> {
155 let md = Into::<MessageDigest>::into(name_alg);
156
157 let oaep_md = Md::from_nid(md.type_()).ok_or(TpmCryptoError::OperationFailed)?;
158
159 let n = BigNum::from_slice(self.n.as_ref()).map_err(|_| TpmCryptoError::OutOfMemory)?;
160 let e = BigNum::from_u32(self.e).map_err(|_| TpmCryptoError::OutOfMemory)?;
161 let rsa = Rsa::from_public_components(n, e).map_err(|_| TpmCryptoError::OperationFailed)?;
162 let pkey = PKey::from_rsa(rsa).map_err(|_| TpmCryptoError::OperationFailed)?;
163
164 let mut ctx = PkeyCtx::new(&pkey).map_err(|_| TpmCryptoError::OutOfMemory)?;
165
166 ctx.encrypt_init()
167 .map_err(|_| TpmCryptoError::OperationFailed)?;
168 ctx.set_rsa_padding(Padding::PKCS1_OAEP)
169 .map_err(|_| TpmCryptoError::OperationFailed)?;
170 ctx.set_rsa_oaep_md(oaep_md)
171 .map_err(|_| TpmCryptoError::OperationFailed)?;
172 ctx.set_rsa_mgf1_md(oaep_md)
173 .map_err(|_| TpmCryptoError::OperationFailed)?;
174 ctx.set_rsa_oaep_label(b"DUPLICATE\0")
175 .map_err(|_| TpmCryptoError::OperationFailed)?;
176
177 let mut encrypted_seed = vec![0; pkey.size()];
178 let len = ctx
179 .encrypt(seed, Some(encrypted_seed.as_mut_slice()))
180 .map_err(|_| TpmCryptoError::OperationFailed)?;
181
182 encrypted_seed.truncate(len);
183 Ok(encrypted_seed)
184 }
185}