aboutsummaryrefslogtreecommitdiff
path: root/openssl
diff options
context:
space:
mode:
authorSteven Fackler <[email protected]>2018-03-10 16:42:33 -0800
committerGitHub <[email protected]>2018-03-10 16:42:33 -0800
commiteb5fda588f83e74701bbcaeb646ca3800275d495 (patch)
tree8cacb5823464c3f4b04831470b385d652722acda /openssl
parentMerge pull request #867 from sfackler/1.1.1-pre2 (diff)
parentSwitches to new type wrapper for RsaPssSaltlen (diff)
downloadrust-openssl-eb5fda588f83e74701bbcaeb646ca3800275d495.tar.xz
rust-openssl-eb5fda588f83e74701bbcaeb646ca3800275d495.zip
Merge pull request #862 from bkchr/sign_verifier
Adds new functions for Verifier/Signer
Diffstat (limited to 'openssl')
-rw-r--r--openssl/src/pkey.rs37
-rw-r--r--openssl/src/rsa.rs1
-rw-r--r--openssl/src/sign.rs111
3 files changed, 148 insertions, 1 deletions
diff --git a/openssl/src/pkey.rs b/openssl/src/pkey.rs
index 8f7c4e4e..506c6db7 100644
--- a/openssl/src/pkey.rs
+++ b/openssl/src/pkey.rs
@@ -70,6 +70,28 @@ pub enum Public {}
/// A tag type indicating that a key has private components.
pub enum Private {}
+/// The Oids that identify the type of a key.
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub struct Oid(c_int);
+
+impl Oid {
+ /// Creates a `Oid` from an integer representation.
+ pub fn from_raw(value: c_int) -> Oid {
+ Oid(value)
+ }
+
+ /// Returns the integer representation of `Oid`.
+ pub fn as_raw(&self) -> c_int {
+ self.0
+ }
+
+ pub const RSA: Oid = Oid(ffi::EVP_PKEY_RSA);
+ pub const HMAC: Oid = Oid(ffi::EVP_PKEY_HMAC);
+ pub const DSA: Oid = Oid(ffi::EVP_PKEY_DSA);
+ pub const DH: Oid = Oid(ffi::EVP_PKEY_DH);
+ pub const EC: Oid = Oid(ffi::EVP_PKEY_EC);
+}
+
/// A trait indicating that a key has parameters.
pub unsafe trait HasParams {}
@@ -155,6 +177,17 @@ impl<T> PKeyRef<T> {
Ok(EcKey::from_ptr(ec_key))
}
}
+
+ /// Returns the Oid that represents the type of this key.
+ ///
+ /// This corresponds to [`EVP_PKEY_id`].
+ ///
+ /// [`EVP_PKEY_id`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_PKEY_id.html
+ pub fn oid(&self) -> Oid {
+ unsafe {
+ Oid::from_raw(ffi::EVP_PKEY_id(self.as_ptr()))
+ }
+ }
}
impl<T> PKeyRef<T>
@@ -531,6 +564,7 @@ mod tests {
let rsa = Rsa::generate(2048).unwrap();
let pkey = PKey::from_rsa(rsa).unwrap();
pkey.rsa().unwrap();
+ assert_eq!(pkey.oid(), Oid::RSA);
assert!(pkey.dsa().is_err());
}
@@ -539,6 +573,7 @@ mod tests {
let dsa = Dsa::generate(2048).unwrap();
let pkey = PKey::from_dsa(dsa).unwrap();
pkey.dsa().unwrap();
+ assert_eq!(pkey.oid(), Oid::DSA);
assert!(pkey.rsa().is_err());
}
@@ -548,6 +583,7 @@ mod tests {
let dh = Dh::params_from_pem(dh).unwrap();
let pkey = PKey::from_dh(dh).unwrap();
pkey.dh().unwrap();
+ assert_eq!(pkey.oid(), Oid::DH);
assert!(pkey.rsa().is_err());
}
@@ -556,6 +592,7 @@ mod tests {
let ec_key = EcKey::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
let pkey = PKey::from_ec_key(ec_key).unwrap();
pkey.ec_key().unwrap();
+ assert_eq!(pkey.oid(), Oid::EC);
assert!(pkey.rsa().is_err());
}
}
diff --git a/openssl/src/rsa.rs b/openssl/src/rsa.rs
index 02240948..6a591b69 100644
--- a/openssl/src/rsa.rs
+++ b/openssl/src/rsa.rs
@@ -63,6 +63,7 @@ impl Padding {
pub const NONE: Padding = Padding(ffi::RSA_NO_PADDING);
pub const PKCS1: Padding = Padding(ffi::RSA_PKCS1_PADDING);
pub const PKCS1_OAEP: Padding = Padding(ffi::RSA_PKCS1_OAEP_PADDING);
+ pub const PKCS1_PSS: Padding = Padding(ffi::RSA_PKCS1_PSS_PADDING);
}
generic_foreign_type_and_impl_send_sync! {
diff --git a/openssl/src/sign.rs b/openssl/src/sign.rs
index 8911a69a..6a49cb49 100644
--- a/openssl/src/sign.rs
+++ b/openssl/src/sign.rs
@@ -66,6 +66,7 @@ use foreign_types::ForeignTypeRef;
use std::io::{self, Write};
use std::marker::PhantomData;
use std::ptr;
+use libc::c_int;
use {cvt, cvt_p};
use hash::MessageDigest;
@@ -78,6 +79,28 @@ use ffi::{EVP_MD_CTX_free, EVP_MD_CTX_new};
#[cfg(any(ossl101, ossl102))]
use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_free};
+/// Salt lengths that must be used with `set_rsa_pss_saltlen`.
+pub struct RsaPssSaltlen(c_int);
+
+impl RsaPssSaltlen {
+ /// Returns the integer representation of `RsaPssSaltlen`.
+ fn as_raw(&self) -> c_int {
+ self.0
+ }
+
+ /// Sets the salt length to the given value.
+ pub fn custom(val: c_int) -> RsaPssSaltlen {
+ RsaPssSaltlen(val)
+ }
+
+ /// The salt length is set to the digest length.
+ /// Corresponds to the special value `-1`.
+ pub const DIGEST_LENGTH: RsaPssSaltlen = RsaPssSaltlen(-1);
+ /// The salt length is set to the maximum permissible value.
+ /// Corresponds to the special value `-2`.
+ pub const MAXIMUM_LENGTH: RsaPssSaltlen = RsaPssSaltlen(-2);
+}
+
/// A type which computes cryptographic signatures of data.
pub struct Signer<'a> {
md_ctx: *mut ffi::EVP_MD_CTX,
@@ -163,6 +186,38 @@ impl<'a> Signer<'a> {
}
}
+ /// Sets the RSA PSS salt length.
+ ///
+ /// This is only useful for RSA keys.
+ ///
+ /// This corresponds to [`EVP_PKEY_CTX_set_rsa_pss_saltlen`].
+ ///
+ /// [`EVP_PKEY_CTX_set_rsa_pss_saltlen`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_PKEY_CTX_set_rsa_pss_saltlen.html
+ pub fn set_rsa_pss_saltlen(&mut self, len: RsaPssSaltlen) -> Result<(), ErrorStack> {
+ unsafe {
+ cvt(ffi::EVP_PKEY_CTX_set_rsa_pss_saltlen(
+ self.pctx,
+ len.as_raw(),
+ )).map(|_| ())
+ }
+ }
+
+ /// Sets the RSA MGF1 algorithm.
+ ///
+ /// This is only useful for RSA keys.
+ ///
+ /// This corresponds to [`EVP_PKEY_CTX_set_rsa_mgf1_md`].
+ ///
+ /// [`EVP_PKEY_CTX_set_rsa_mgf1_md`]: https://www.openssl.org/docs/manmaster/man7/RSA-PSS.html
+ pub fn set_rsa_mgf1_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
+ unsafe {
+ cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md(
+ self.pctx,
+ md.as_ptr() as *mut _,
+ )).map(|_| ())
+ }
+ }
+
/// Feeds more data into the `Signer`.
///
/// OpenSSL documentation at [`EVP_DigestUpdate`].
@@ -326,6 +381,38 @@ impl<'a> Verifier<'a> {
}
}
+ /// Sets the RSA PSS salt length.
+ ///
+ /// This is only useful for RSA keys.
+ ///
+ /// This corresponds to [`EVP_PKEY_CTX_set_rsa_pss_saltlen`].
+ ///
+ /// [`EVP_PKEY_CTX_set_rsa_pss_saltlen`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_PKEY_CTX_set_rsa_pss_saltlen.html
+ pub fn set_rsa_pss_saltlen(&mut self, len: RsaPssSaltlen) -> Result<(), ErrorStack> {
+ unsafe {
+ cvt(ffi::EVP_PKEY_CTX_set_rsa_pss_saltlen(
+ self.pctx,
+ len.as_raw(),
+ )).map(|_| ())
+ }
+ }
+
+ /// Sets the RSA MGF1 algorithm.
+ ///
+ /// This is only useful for RSA keys.
+ ///
+ /// This corresponds to [`EVP_PKEY_CTX_set_rsa_mgf1_md`].
+ ///
+ /// [`EVP_PKEY_CTX_set_rsa_mgf1_md`]: https://www.openssl.org/docs/manmaster/man7/RSA-PSS.html
+ pub fn set_rsa_mgf1_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
+ unsafe {
+ cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md(
+ self.pctx,
+ md.as_ptr() as *mut _,
+ )).map(|_| ())
+ }
+ }
+
/// Feeds more data into the `Verifier`.
///
/// OpenSSL documentation at [`EVP_DigestUpdate`].
@@ -392,7 +479,7 @@ mod test {
use std::iter;
use hash::MessageDigest;
- use sign::{Signer, Verifier};
+ use sign::{Signer, Verifier, RsaPssSaltlen};
use ec::{EcGroup, EcKey};
use nid::Nid;
use rsa::{Padding, Rsa};
@@ -565,4 +652,26 @@ mod test {
verifier.update(b"hello world").unwrap();
assert!(verifier.verify(&signature).unwrap());
}
+
+ #[test]
+ fn rsa_sign_verify() {
+ let key = include_bytes!("../test/rsa.pem");
+ let private_key = Rsa::private_key_from_pem(key).unwrap();
+ let pkey = PKey::from_rsa(private_key).unwrap();
+
+ let mut signer = Signer::new(MessageDigest::sha256(), &pkey).unwrap();
+ signer.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
+ assert_eq!(signer.rsa_padding().unwrap(), Padding::PKCS1_PSS);
+ signer.set_rsa_pss_saltlen(RsaPssSaltlen::DIGEST_LENGTH).unwrap();
+ signer.set_rsa_mgf1_md(MessageDigest::sha256()).unwrap();
+ signer.update(&Vec::from_hex(INPUT).unwrap()).unwrap();
+ let signature = signer.sign_to_vec().unwrap();
+
+ let mut verifier = Verifier::new(MessageDigest::sha256(), &pkey).unwrap();
+ verifier.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
+ verifier.set_rsa_pss_saltlen(RsaPssSaltlen::DIGEST_LENGTH).unwrap();
+ verifier.set_rsa_mgf1_md(MessageDigest::sha256()).unwrap();
+ verifier.update(&Vec::from_hex(INPUT).unwrap()).unwrap();
+ assert!(verifier.verify(&signature).unwrap());
+ }
}