1use crate::{Error, Hash, PublicKey};
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 RsaPublicKey {
26 pub n: Tpm2bPublicKeyRsa,
27 pub e: u32,
28 pub key_bits: u16,
29}
30
31impl TryFrom<&TpmtPublic> for RsaPublicKey {
32 type Error = Error;
33
34 fn try_from(public: &TpmtPublic) -> Result<Self, Self::Error> {
35 if public.object_type != TpmAlgId::Rsa {
36 return Err(Error::InvalidRsaParameters);
37 }
38
39 let params = match &public.parameters {
40 TpmuPublicParms::Rsa(params) => Ok(params),
41 _ => Err(Error::InvalidRsaParameters),
42 }?;
43
44 let n = match &public.unique {
45 TpmuPublicId::Rsa(n) => Ok(*n),
46 _ => Err(Error::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 RsaPublicKey {
64 type Error = Error;
65
66 fn try_from(pkey: &PKey<Private>) -> Result<Self, Self::Error> {
67 let rsa = pkey.rsa().map_err(|_| Error::InvalidRsaParameters)?;
68 let n = Tpm2bPublicKeyRsa::try_from(rsa.n().to_vec().as_slice())
69 .map_err(|_| Error::InvalidRsaParameters)?;
70
71 let e_bn = rsa.e();
72 if e_bn.is_negative() || e_bn.num_bits() > 32 {
73 return Err(Error::InvalidRsaParameters);
74 }
75 let e_bytes = e_bn.to_vec();
76 let mut e_buf = [0u8; 4];
77 e_buf[4 - e_bytes.len()..].copy_from_slice(&e_bytes);
78 let e = u32::from_be_bytes(e_buf);
79
80 let key_bits = u16::try_from(rsa.size() * 8).map_err(|_| Error::InvalidRsaParameters)?;
81
82 Ok(Self { n, e, key_bits })
83 }
84}
85
86impl PublicKey for RsaPublicKey {
87 fn from_der(bytes: &[u8]) -> Result<(Self, Vec<u8>), Error> {
88 let pkey = PKey::private_key_from_der(bytes).map_err(|_| Error::OperationFailed)?;
89 let public_key = RsaPublicKey::try_from(&pkey)?;
90 let rsa = pkey.rsa().map_err(|_| Error::InvalidRsaParameters)?;
91 let sensitive = rsa.p().ok_or(Error::OperationFailed)?.to_vec();
92 Ok((public_key, sensitive))
93 }
94
95 fn to_public(&self, hash_alg: TpmAlgId, symmetric: TpmtSymDefObject) -> TpmtPublic {
96 TpmtPublic {
97 object_type: TpmAlgId::Rsa,
98 name_alg: hash_alg,
99 object_attributes: TpmaObject::USER_WITH_AUTH | TpmaObject::DECRYPT,
100 auth_policy: Tpm2bDigest::default(),
101 parameters: TpmuPublicParms::Rsa(TpmsRsaParms {
102 symmetric,
103 scheme: TpmtRsaScheme {
104 scheme: TpmAlgId::Oaep,
105 details: TpmuAsymScheme::Hash(TpmsSchemeHash { hash_alg }),
106 },
107 key_bits: self.key_bits,
108 exponent: 0,
109 }),
110 unique: TpmuPublicId::Rsa(self.n),
111 }
112 }
113
114 fn to_seed(
115 &self,
116 name_alg: Hash,
117 _rng: &mut (impl RngCore + CryptoRng),
118 ) -> Result<(Vec<u8>, Tpm2bEncryptedSecret), Error> {
119 let seed_size = name_alg.size();
120 let mut seed = vec![0u8; seed_size];
121 rand_bytes(&mut seed).map_err(|_| Error::OperationFailed)?;
122
123 let encrypted_seed_bytes = self.oaep(name_alg, &seed)?;
124
125 let encrypted_seed = Tpm2bEncryptedSecret::try_from(encrypted_seed_bytes.as_slice())
126 .map_err(|_| Error::OutOfMemory)?;
127
128 Ok((seed, encrypted_seed))
129 }
130}
131
132impl RsaPublicKey {
133 fn oaep(&self, name_alg: Hash, seed: &[u8]) -> Result<Vec<u8>, Error> {
144 let md = Into::<MessageDigest>::into(name_alg);
145
146 let oaep_md = Md::from_nid(md.type_()).ok_or(Error::OperationFailed)?;
147
148 let n = BigNum::from_slice(self.n.as_ref()).map_err(|_| Error::OutOfMemory)?;
149 let e = BigNum::from_u32(self.e).map_err(|_| Error::OutOfMemory)?;
150 let rsa = Rsa::from_public_components(n, e).map_err(|_| Error::OperationFailed)?;
151 let pkey = PKey::from_rsa(rsa).map_err(|_| Error::OperationFailed)?;
152
153 let mut ctx = PkeyCtx::new(&pkey).map_err(|_| Error::OutOfMemory)?;
154
155 ctx.encrypt_init().map_err(|_| Error::OperationFailed)?;
156 ctx.set_rsa_padding(Padding::PKCS1_OAEP)
157 .map_err(|_| Error::OperationFailed)?;
158 ctx.set_rsa_oaep_md(oaep_md)
159 .map_err(|_| Error::OperationFailed)?;
160 ctx.set_rsa_mgf1_md(oaep_md)
161 .map_err(|_| Error::OperationFailed)?;
162 ctx.set_rsa_oaep_label(b"DUPLICATE\0")
163 .map_err(|_| Error::OperationFailed)?;
164
165 let mut encrypted_seed = vec![0; pkey.size()];
166 let len = ctx
167 .encrypt(seed, Some(encrypted_seed.as_mut_slice()))
168 .map_err(|_| Error::OperationFailed)?;
169
170 encrypted_seed.truncate(len);
171 Ok(encrypted_seed)
172 }
173}