opentitanlib/crypto/
rsa.rs1use anyhow::{Context, Result, anyhow, bail, ensure};
6use num_bigint_dig::{BigInt, BigUint, Sign::Minus, traits::ModInverse};
7use rand::rngs::OsRng;
8use rsa::pkcs1::{DecodeRsaPublicKey, EncodeRsaPublicKey};
9use rsa::pkcs1v15::Pkcs1v15Sign;
10use rsa::pkcs8::{DecodePrivateKey, DecodePublicKey, EncodePrivateKey};
11use rsa::traits::PublicKeyParts;
12use serde::{Deserialize, Serialize};
13use serde_annotate::Annotate;
14use sha2::Sha256;
15use std::fs::File;
16use std::io::{Read, Write};
17use std::ops::Deref;
18use std::ops::Shl;
19use std::path::{Path, PathBuf};
20use std::str::FromStr;
21
22use super::Error;
23use crate::crypto::sha256::Sha256Digest;
24use crate::util::bigint::fixed_size_bigint;
25
26const MODULUS_BIT_LEN: usize = 3072;
27const EXPONENT_BIT_LEN: usize = 17;
28const SIGNATURE_BIT_LEN: usize = 3072;
29const RR_BIT_LEN: usize = 3072;
30const OTBN_BITS: usize = 256;
31
32fixed_size_bigint!(Modulus, MODULUS_BIT_LEN);
33fixed_size_bigint!(Exponent, EXPONENT_BIT_LEN);
34fixed_size_bigint!(Signature, at_most SIGNATURE_BIT_LEN);
35fixed_size_bigint!(RR, at_most RR_BIT_LEN);
36fixed_size_bigint!(N0Inv, at_most OTBN_BITS);
37
38fn validate_key(key: &impl PublicKeyParts) -> Result<()> {
40 if key.n().bits() != MODULUS_BIT_LEN || key.e() != &BigUint::from(65537u32) {
41 bail!(Error::InvalidPublicKey(anyhow!("bad modulus or exponent")));
42 } else {
43 Ok(())
44 }
45}
46
47#[derive(Debug)]
51pub struct RsaPublicKey {
52 key: rsa::RsaPublicKey,
53}
54
55impl RsaPublicKey {
56 pub fn new(n: Modulus) -> Result<RsaPublicKey> {
58 Ok(RsaPublicKey {
59 key: rsa::RsaPublicKey::new(
60 BigUint::from_bytes_le(n.to_le_bytes().as_slice()),
61 BigUint::from(65537u32),
62 )
63 .map_err(|e| Error::InvalidPublicKey(anyhow!(e)))?,
64 })
65 }
66
67 pub fn from_pkcs1_der_file<P: Into<PathBuf>>(der_file: P) -> Result<RsaPublicKey> {
69 let der_file = der_file.into();
70 match rsa::RsaPublicKey::read_pkcs1_der_file(&der_file)
71 .or_else(|_| rsa::RsaPublicKey::read_public_key_der_file(&der_file))
72 {
73 Ok(key) => {
74 validate_key(&key)?;
75 Ok(Self { key })
76 }
77 Err(err) => bail!(Error::InvalidDerFile {
78 der: der_file,
79 source: anyhow!(err),
80 }),
81 }
82 }
83
84 pub fn to_pkcs1_der_file<P: Into<PathBuf>>(&self, der_file: P) -> Result<()> {
86 let der_file = der_file.into();
87 self.key
88 .write_pkcs1_der_file(&der_file)
89 .map_err(|e| Error::WriteFailed {
90 file: der_file.to_owned(),
91 source: anyhow!(e),
92 })?;
93 Ok(())
94 }
95
96 pub fn from_private_key(private_key: &RsaPrivateKey) -> Self {
98 Self {
99 key: rsa::RsaPublicKey::from(&private_key.key),
100 }
101 }
102
103 pub fn modulus_num_bits(&self) -> usize {
105 self.key.n().bits()
106 }
107
108 pub fn modulus(&self) -> Modulus {
110 Modulus::from_le_bytes(self.key.n().to_bytes_le()).unwrap()
112 }
113
114 pub fn exponent(&self) -> Exponent {
116 Exponent::from_le_bytes(self.key.e().to_bytes_le()).unwrap()
118 }
119
120 pub fn n0_inv(&self) -> Result<N0Inv> {
122 let base = BigInt::from(1u8) << OTBN_BITS;
123 let n_neg = BigInt::from_biguint(Minus, self.key.n().to_owned());
124 let n0_inv = n_neg
125 .mod_inverse(&base)
126 .and_then(|v| v.to_biguint())
127 .ok_or(Error::KeyComponentComputeFailed)?;
128 Ok(N0Inv::from_le_bytes(n0_inv.to_bytes_le())?)
129 }
130
131 pub fn rr(&self) -> RR {
133 let rr = BigUint::from(1u8).shl(2 * self.modulus_num_bits()) % self.key.n();
134 RR::from_le_bytes(rr.to_bytes_le()).unwrap()
136 }
137
138 pub fn verify(&self, digest: &Sha256Digest, signature: &Signature) -> Result<()> {
140 self.key
141 .verify(
142 Pkcs1v15Sign::new::<Sha256>(),
143 digest.to_be_bytes().as_slice(),
144 signature.to_be_bytes().as_slice(),
145 )
146 .map_err(|e| anyhow!(Error::VerifyFailed(anyhow!(e))))
147 }
148}
149
150#[derive(Debug, Clone)]
154pub struct RsaPrivateKey {
155 key: rsa::RsaPrivateKey,
156}
157
158impl RsaPrivateKey {
159 pub fn new() -> Result<Self> {
161 let mut rng = OsRng;
162 Ok(Self {
163 key: rsa::RsaPrivateKey::new_with_exp(&mut rng, 3072, &BigUint::from(65537u32))
164 .map_err(|e| Error::GenerateFailed(anyhow!(e)))?,
165 })
166 }
167
168 pub fn from_pkcs8_der_file<P: Into<PathBuf>>(der_file: P) -> Result<Self> {
170 let der_file = der_file.into();
171 match rsa::RsaPrivateKey::read_pkcs8_der_file(&der_file) {
172 Ok(key) => {
173 validate_key(&key)?;
174 Ok(Self { key })
175 }
176 Err(err) => bail!(Error::InvalidDerFile {
177 der: der_file,
178 source: anyhow!(err),
179 }),
180 }
181 }
182
183 pub fn to_pkcs8_der_file<P: Into<PathBuf>>(&self, der_file: P) -> Result<()> {
185 let der_file = der_file.into();
186 self.key
187 .write_pkcs8_der_file(&der_file)
188 .map_err(|e| Error::WriteFailed {
189 file: der_file,
190 source: anyhow!(e),
191 })?;
192 Ok(())
193 }
194
195 pub fn sign(&self, digest: &Sha256Digest) -> Result<Signature> {
197 let signature = self
198 .key
199 .sign(Pkcs1v15Sign::new::<Sha256>(), &digest.to_be_bytes())
200 .map_err(|e| Error::SignFailed(anyhow!(e)))?;
201 Ok(Signature::from_be_bytes(signature)?)
202 }
203}
204
205impl Signature {
206 pub fn read_from_file(path: &Path) -> Result<Signature> {
208 let err = |e: std::io::Error| Error::ReadFailed {
209 file: path.to_owned(),
210 source: anyhow!(e),
211 };
212 let mut file = File::open(path).map_err(err)?;
213 let mut buf = Vec::<u8>::new();
214 file.read_to_end(&mut buf).map_err(err)?;
215 Ok(Signature::from_le_bytes(buf.as_slice())?)
216 }
217
218 pub fn write_to_file(&self, path: &Path) -> Result<()> {
220 let err = |e: std::io::Error| Error::WriteFailed {
221 file: path.to_owned(),
222 source: anyhow!(e),
223 };
224 let mut file = File::create(path).map_err(err)?;
225 file.write_all(self.to_le_bytes().as_mut_slice())
226 .map_err(err)?;
227 Ok(())
228 }
229}
230
231impl Deref for RsaPublicKey {
232 type Target = rsa::RsaPublicKey;
233
234 fn deref(&self) -> &Self::Target {
235 &self.key
236 }
237}
238
239impl Deref for RsaPrivateKey {
240 type Target = rsa::RsaPrivateKey;
241
242 fn deref(&self) -> &Self::Target {
243 &self.key
244 }
245}
246
247#[derive(Debug, Serialize, Deserialize, Annotate)]
248pub struct RsaRawPublicKey {
249 #[serde(with = "serde_bytes")]
250 #[annotate(format = hexstr)]
251 pub modulus: Vec<u8>,
252 #[serde(with = "serde_bytes")]
253 #[annotate(format = hexstr)]
254 pub n0_inv: Vec<u8>,
255}
256
257impl Default for RsaRawPublicKey {
258 fn default() -> Self {
259 Self {
260 modulus: vec![0; 384],
261 n0_inv: vec![0; 32],
262 }
263 }
264}
265
266impl TryFrom<&RsaPublicKey> for RsaRawPublicKey {
267 type Error = Error;
268 fn try_from(v: &RsaPublicKey) -> Result<Self, Self::Error> {
269 Ok(Self {
270 modulus: v.modulus().to_le_bytes().to_vec(),
271 n0_inv: v.n0_inv().map_err(Error::Other)?.to_le_bytes().to_vec(),
272 })
273 }
274}
275
276impl TryFrom<RsaPublicKey> for RsaRawPublicKey {
277 type Error = Error;
278 fn try_from(v: RsaPublicKey) -> Result<Self, Self::Error> {
279 RsaRawPublicKey::try_from(&v)
280 }
281}
282
283impl FromStr for RsaRawPublicKey {
284 type Err = Error;
285 fn from_str(s: &str) -> Result<Self, Self::Err> {
286 let key = RsaPublicKey::from_pkcs1_der_file(s)
287 .with_context(|| format!("Failed to load {s}"))
288 .map_err(Error::Other)?;
289 RsaRawPublicKey::try_from(&key)
290 }
291}
292
293impl RsaRawPublicKey {
294 pub const SIZE: usize = 384 + 32;
295 pub fn read(src: &mut impl Read) -> Result<Self> {
296 let mut key = Self::default();
297 src.read_exact(&mut key.modulus)?;
298 src.read_exact(&mut key.n0_inv)?;
299 Ok(key)
300 }
301
302 pub fn write(&self, dest: &mut impl Write) -> Result<()> {
303 ensure!(
304 self.modulus.len() == 384,
305 Error::InvalidPublicKey(anyhow!("bad modulus length: {}", self.modulus.len()))
306 );
307 ensure!(
308 self.n0_inv.len() == 32,
309 Error::InvalidPublicKey(anyhow!("bad n0_inv length: {}", self.n0_inv.len()))
310 );
311 dest.write_all(&self.modulus)?;
312 dest.write_all(&self.n0_inv)?;
313 Ok(())
314 }
315}