Skip to content

Commit 75cb9b7

Browse files
authored
Merge pull request #347 from fortanix/mz/rsa-key-from-components
Add Pk::private_from_rsa_components and Pk::public_from_rsa_components
2 parents 8cd9a8d + 34f15f6 commit 75cb9b7

File tree

1 file changed

+96
-2
lines changed

1 file changed

+96
-2
lines changed

mbedtls/src/pk/mod.rs

Lines changed: 96 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,34 @@ const CUSTOM_PK_INFO: pk_info_t = {
138138
}
139139
};
140140

141+
/// RSA components for constructing a private key.
142+
pub enum RsaPrivateComponents<'a> {
143+
WithPrimes {
144+
/// Private 1st prime
145+
p: &'a Mpi,
146+
/// Private 2nd prime
147+
q: &'a Mpi,
148+
/// Public exponent
149+
e: &'a Mpi,
150+
},
151+
WithPrivateExponent {
152+
/// Public modulus
153+
n: &'a Mpi,
154+
/// Private exponent
155+
d: &'a Mpi,
156+
/// Public exponent
157+
e: &'a Mpi,
158+
},
159+
}
160+
161+
/// RSA components for constructing a public key.
162+
pub struct RsaPublicComponents<'a> {
163+
/// Public modulus
164+
pub n: &'a Mpi,
165+
/// Public exponent
166+
pub e: &'a Mpi,
167+
}
168+
141169
// If this changes then certificate.rs unsafe code in public_key needs to also
142170
// change.
143171
define!(
@@ -200,7 +228,7 @@ define!(
200228
// - Only const access to context: eckey_check_pair, eckey_get_bitlen,
201229
// eckey_can_do, eckey_check_pair
202230
//
203-
// - Const acccess / copies context to a stack based variable eckey_verify_wrap,
231+
// - Const access / copies context to a stack based variable eckey_verify_wrap,
204232
// eckey_sign_wrap: ../../../mbedtls-sys/vendor/crypto/library/pk_wrap.c:251
205233
// creates a stack ecdsa variable and uses ctx to initialize it. ctx is passed
206234
// as 'key', a const pointer to mbedtls_ecdsa_from_keypair( &ecdsa, ctx )
@@ -348,7 +376,7 @@ Please use `private_from_ec_components_with_rng` instead."
348376
///
349377
/// This function will return an error if:
350378
///
351-
/// * Fails to genearte `EcPoint` from given EcGroup in `curve`.
379+
/// * Fails to generate `EcPoint` from given EcGroup in `curve`.
352380
/// * The underlying C `mbedtls_pk_setup` function fails to set up the `Pk` context.
353381
/// * The `EcPoint::mul` function fails to generate the public key point.
354382
pub fn private_from_ec_components_with_rng<F: Random>(mut curve: EcGroup, private_key: Mpi, rng: &mut F) -> Result<Pk> {
@@ -376,6 +404,39 @@ Please use `private_from_ec_components_with_rng` instead."
376404
Ok(ret)
377405
}
378406

407+
/// Construct a private key from RSA components.
408+
pub fn private_from_rsa_components(components: RsaPrivateComponents<'_>) -> Result<Pk> {
409+
let mut ret = Self::init();
410+
let (n, p, q, d, e) = match components {
411+
RsaPrivateComponents::WithPrimes { p, q, e } => (None, Some(p), Some(q), None, Some(e)),
412+
RsaPrivateComponents::WithPrivateExponent { n, d, e } => (Some(n), None, None, Some(d), Some(e)),
413+
};
414+
let to_ptr = |mpi: Option<&Mpi>| match mpi {
415+
None => ptr::null(),
416+
Some(mpi) => mpi.handle(),
417+
};
418+
unsafe {
419+
pk_setup(&mut ret.inner, pk_info_from_type(Type::Rsa.into())).into_result()?;
420+
let ctx = ret.inner.pk_ctx as *mut rsa_context;
421+
rsa_import(ctx, to_ptr(n), to_ptr(p), to_ptr(q), to_ptr(d), to_ptr(e)).into_result()?;
422+
rsa_complete(ctx).into_result()?;
423+
}
424+
Ok(ret)
425+
}
426+
427+
/// Construct a public key from RSA components.
428+
pub fn public_from_rsa_components(components: RsaPublicComponents<'_>) -> Result<Pk> {
429+
let mut ret = Self::init();
430+
let RsaPublicComponents { n, e } = components;
431+
unsafe {
432+
pk_setup(&mut ret.inner, pk_info_from_type(Type::Rsa.into())).into_result()?;
433+
let ctx = ret.inner.pk_ctx as *mut rsa_context;
434+
rsa_import(ctx, n.handle(), ptr::null(), ptr::null(), ptr::null(), e.handle()).into_result()?;
435+
rsa_complete(ctx).into_result()?;
436+
}
437+
Ok(ret)
438+
}
439+
379440
pub fn public_custom_algo(algo_id: &[u64], pk: &[u8]) -> Result<Pk> {
380441
let mut ret = Self::init();
381442
unsafe {
@@ -1564,4 +1625,37 @@ iy6KC991zzvaWY/Ys+q/84Afqa+0qJKQnPuy/7F5GkVdQA/lfbhi
15641625
assert_eq!(l.unwrap(), LEN);
15651626
}
15661627
}
1628+
1629+
#[test]
1630+
fn private_from_rsa_components_sanity() {
1631+
let mut pk = Pk::generate_rsa(&mut crate::test_support::rand::test_rng(), 2048, 0x10001).unwrap();
1632+
let components = RsaPrivateComponents::WithPrimes {
1633+
p: &pk.rsa_private_prime1().unwrap(),
1634+
q: &pk.rsa_private_prime2().unwrap(),
1635+
e: &Mpi::new(pk.rsa_public_exponent().unwrap() as _).unwrap(),
1636+
};
1637+
let mut pk2 = Pk::private_from_rsa_components(components).unwrap();
1638+
assert_eq!(pk.write_private_der_vec().unwrap(), pk2.write_private_der_vec().unwrap());
1639+
1640+
let components = RsaPrivateComponents::WithPrivateExponent {
1641+
n: &pk.rsa_public_modulus().unwrap(),
1642+
d: &pk.rsa_private_exponent().unwrap(),
1643+
e: &Mpi::new(pk.rsa_public_exponent().unwrap() as _).unwrap(),
1644+
};
1645+
let mut pk3 = Pk::private_from_rsa_components(components).unwrap();
1646+
assert_eq!(pk.write_private_der_vec().unwrap(), pk3.write_private_der_vec().unwrap());
1647+
}
1648+
1649+
#[test]
1650+
fn public_from_rsa_components_sanity() {
1651+
let mut pk = Pk::generate_rsa(&mut crate::test_support::rand::test_rng(), 2048, 0x10001).unwrap();
1652+
let mut pk = Pk::from_public_key(&pk.write_public_der_vec().unwrap()).unwrap();
1653+
1654+
let components = RsaPublicComponents {
1655+
n: &pk.rsa_public_modulus().unwrap(),
1656+
e: &Mpi::new(pk.rsa_public_exponent().unwrap() as _).unwrap(),
1657+
};
1658+
let mut pk2 = Pk::public_from_rsa_components(components).unwrap();
1659+
assert_eq!(pk.write_public_der_vec().unwrap(), pk2.write_public_der_vec().unwrap());
1660+
}
15671661
}

0 commit comments

Comments
 (0)