Skip to content

Commit e849e8f

Browse files
bors[bot]Pagten
andauthored
Merge #125
125: Add support for RSA OAEP encryption/decryption with custom labels r=AdrianCX a=Pagten This exposes the `mbedtls_rsa_rsaes_oaep_encrypt()` and `mbedtls_rsa_rsaes_oaep_decrypt()` functions in rust-mbedtls. Co-authored-by: Pieter Agten <[email protected]>
2 parents 5ab60f3 + 36357e7 commit e849e8f

File tree

1 file changed

+102
-0
lines changed

1 file changed

+102
-0
lines changed

mbedtls/src/pk/mod.rs

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,42 @@ impl Pk {
539539
Ok(ret)
540540
}
541541

542+
/// Decrypt using a custom label.
543+
///
544+
/// This function may only be called on an RSA key with its padding set to RSA_PKCS_V21.
545+
pub fn decrypt_with_label<F: Random>(
546+
&mut self,
547+
cipher: &[u8],
548+
plain: &mut [u8],
549+
rng: &mut F,
550+
label: &[u8],
551+
) -> Result<usize> {
552+
if self.pk_type() != Type::Rsa {
553+
return Err(Error::PkTypeMismatch);
554+
}
555+
let ctx = self.inner.pk_ctx as *mut rsa_context;
556+
if unsafe { (*ctx).padding != RSA_PKCS_V21 } {
557+
return Err(Error::RsaInvalidPadding);
558+
}
559+
560+
let mut ret = 0usize;
561+
unsafe {
562+
rsa_rsaes_oaep_decrypt(
563+
ctx,
564+
Some(F::call),
565+
rng.data_ptr(),
566+
RSA_PRIVATE,
567+
label.as_ptr(),
568+
label.len(),
569+
&mut ret,
570+
cipher.as_ptr(),
571+
plain.as_mut_ptr(),
572+
plain.len(),
573+
).into_result()?;
574+
}
575+
Ok(ret)
576+
}
577+
542578
pub fn encrypt<F: Random>(
543579
&mut self,
544580
plain: &[u8],
@@ -562,6 +598,44 @@ impl Pk {
562598
Ok(ret)
563599
}
564600

601+
/// Encrypt using a custom label.
602+
///
603+
/// This function may only be called on an RSA key with its padding set to RSA_PKCS_V21.
604+
pub fn encrypt_with_label<F: Random>(
605+
&mut self,
606+
plain: &[u8],
607+
cipher: &mut [u8],
608+
rng: &mut F,
609+
label: &[u8],
610+
) -> Result<usize> {
611+
if self.pk_type() != Type::Rsa {
612+
return Err(Error::PkTypeMismatch);
613+
}
614+
let ctx = self.inner.pk_ctx as *mut rsa_context;
615+
if unsafe { (*ctx).padding != RSA_PKCS_V21 } {
616+
return Err(Error::RsaInvalidPadding);
617+
}
618+
let olen = self.len() / 8;
619+
if cipher.len() < olen {
620+
return Err(Error::RsaOutputTooLarge);
621+
}
622+
623+
unsafe {
624+
rsa_rsaes_oaep_encrypt(
625+
ctx,
626+
Some(F::call),
627+
rng.data_ptr(),
628+
RSA_PUBLIC,
629+
label.as_ptr(),
630+
label.len(),
631+
plain.len(),
632+
plain.as_ptr(),
633+
cipher.as_mut_ptr()
634+
).into_result()?;
635+
}
636+
Ok(olen)
637+
}
638+
565639
/// Sign the hash `hash` of type `md`, placing the signature in `sig`. `rng` must be a
566640
/// cryptographically secure RNG.
567641
///
@@ -1129,6 +1203,34 @@ iy6KC991zzvaWY/Ys+q/84Afqa+0qJKQnPuy/7F5GkVdQA/lfbhi
11291203
);
11301204
}
11311205

1206+
#[test]
1207+
fn rsa_encrypt_decrypt_with_label() {
1208+
let mut pk = Pk::from_private_key(TEST_DER, None).unwrap();
1209+
let mut cipher = [0u8; 2048 / 8];
1210+
// set raw decryption padding mode
1211+
pk.set_options(Options::Rsa {
1212+
padding: RsaPadding::Pkcs1V21 { mgf: MdType::Sha256 }
1213+
});
1214+
1215+
let plain = b"testing123";
1216+
let cipher_len = pk.encrypt_with_label(plain, &mut cipher,
1217+
&mut crate::test_support::rand::test_rng(),
1218+
b"MY_LABEL").unwrap();
1219+
assert_eq!(cipher_len, cipher.len());
1220+
1221+
let mut plain_decrypted = [0u8; 10];
1222+
let plain_len = pk.decrypt_with_label(&cipher, &mut plain_decrypted,
1223+
&mut crate::test_support::rand::test_rng(),
1224+
b"MY_LABEL").unwrap();
1225+
assert_eq!(plain_len, plain.len());
1226+
assert_eq!(&plain_decrypted, plain);
1227+
1228+
assert_eq!(pk.decrypt_with_label(&cipher, &mut plain_decrypted,
1229+
&mut crate::test_support::rand::test_rng(),
1230+
b"WRONG_LABEL").unwrap_err(),
1231+
Error::RsaInvalidPadding);
1232+
}
1233+
11321234
#[test]
11331235
fn rsa_sign_with_none_padding() {
11341236
let mut pk =

0 commit comments

Comments
 (0)