summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Gaynor <alex.gaynor@gmail.com>2023-05-14 16:37:20 -0400
committerGitHub <noreply@github.com>2023-05-15 04:37:20 +0800
commit4fc8e9aaa12f0b69fca0f36c544543aefb9c5d03 (patch)
tree536f8a838a5fa346156a50a56444afbb3cb011b8
parentcff3c8fee74ba08cc0ce4b67bbb635f73270f8b3 (diff)
downloadcryptography-4fc8e9aaa12f0b69fca0f36c544543aefb9c5d03.tar.gz
Move code to sign.rs (#8922)
-rw-r--r--src/rust/src/x509/certificate.rs140
-rw-r--r--src/rust/src/x509/sign.rs143
2 files changed, 141 insertions, 142 deletions
diff --git a/src/rust/src/x509/certificate.rs b/src/rust/src/x509/certificate.rs
index 34e9ec0ec..3446bbbbb 100644
--- a/src/rust/src/x509/certificate.rs
+++ b/src/rust/src/x509/certificate.rs
@@ -17,28 +17,10 @@ use cryptography_x509::extensions::{
SequenceOfSubtrees, UserNotice,
};
use cryptography_x509::{common, name, oid};
-use once_cell::sync::Lazy;
use pyo3::{IntoPy, ToPyObject};
use std::collections::hash_map::DefaultHasher;
-use std::collections::HashMap;
use std::hash::{Hash, Hasher};
-// This is similar to a hashmap in ocsp.rs but contains more hash algorithms
-// that aren't allowable in OCSP
-static HASH_OIDS_TO_HASH: Lazy<HashMap<&asn1::ObjectIdentifier, &str>> = Lazy::new(|| {
- let mut h = HashMap::new();
- h.insert(&oid::SHA1_OID, "SHA1");
- h.insert(&oid::SHA224_OID, "SHA224");
- h.insert(&oid::SHA256_OID, "SHA256");
- h.insert(&oid::SHA384_OID, "SHA384");
- h.insert(&oid::SHA512_OID, "SHA512");
- h.insert(&oid::SHA3_224_OID, "SHA3_224");
- h.insert(&oid::SHA3_256_OID, "SHA3_256");
- h.insert(&oid::SHA3_384_OID, "SHA3_384");
- h.insert(&oid::SHA3_512_OID, "SHA3_512");
- h
-});
-
#[ouroboros::self_referencing]
pub(crate) struct OwnedCertificate {
data: pyo3::Py<pyo3::types::PyBytes>,
@@ -269,7 +251,7 @@ impl Certificate {
&self,
py: pyo3::Python<'p>,
) -> Result<&'p pyo3::PyAny, CryptographyError> {
- identify_signature_hash_algorithm(py, &self.raw.borrow_value().signature_alg)
+ sign::identify_signature_hash_algorithm(py, &self.raw.borrow_value().signature_alg)
}
#[getter]
@@ -282,7 +264,7 @@ impl Certificate {
&'p self,
py: pyo3::Python<'p>,
) -> CryptographyResult<&'p pyo3::PyAny> {
- identify_signature_algorithm_parameters(py, &self.raw.borrow_value().signature_alg)
+ sign::identify_signature_algorithm_parameters(py, &self.raw.borrow_value().signature_alg)
}
#[getter]
@@ -880,22 +862,6 @@ pub fn parse_cert_ext<'p>(
}
}
-fn hash_oid_py_hash(
- py: pyo3::Python<'_>,
- oid: asn1::ObjectIdentifier,
-) -> CryptographyResult<&pyo3::PyAny> {
- let hashes = py.import(pyo3::intern!(py, "cryptography.hazmat.primitives.hashes"))?;
- match HASH_OIDS_TO_HASH.get(&oid) {
- Some(alg_name) => Ok(hashes.getattr(*alg_name)?.call0()?),
- None => Err(CryptographyError::from(
- exceptions::UnsupportedAlgorithm::new_err(format!(
- "Signature algorithm OID: {} not recognized",
- &oid
- )),
- )),
- }
-}
-
pub(crate) fn time_from_py(
py: pyo3::Python<'_>,
val: &pyo3::PyAny,
@@ -994,108 +960,6 @@ pub(crate) fn set_bit(vals: &mut [u8], n: usize, set: bool) {
}
}
-pub(crate) fn identify_signature_hash_algorithm<'p>(
- py: pyo3::Python<'p>,
- signature_algorithm: &common::AlgorithmIdentifier<'_>,
-) -> CryptographyResult<&'p pyo3::PyAny> {
- let sig_oids_to_hash = py
- .import(pyo3::intern!(py, "cryptography.hazmat._oid"))?
- .getattr(pyo3::intern!(py, "_SIG_OIDS_TO_HASH"))?;
- match &signature_algorithm.params {
- common::AlgorithmParameters::RsaPss(opt_pss) => {
- let pss = opt_pss.as_ref().ok_or_else(|| {
- pyo3::exceptions::PyValueError::new_err("Invalid RSA PSS parameters")
- })?;
- hash_oid_py_hash(py, pss.hash_algorithm.oid().clone())
- }
- _ => {
- let py_sig_alg_oid = oid_to_py_oid(py, signature_algorithm.oid())?;
- let hash_alg = sig_oids_to_hash.get_item(py_sig_alg_oid);
- match hash_alg {
- Ok(data) => Ok(data),
- Err(_) => Err(CryptographyError::from(
- exceptions::UnsupportedAlgorithm::new_err(format!(
- "Signature algorithm OID: {} not recognized",
- signature_algorithm.oid()
- )),
- )),
- }
- }
- }
-}
-
-pub(crate) fn identify_signature_algorithm_parameters<'p>(
- py: pyo3::Python<'p>,
- signature_algorithm: &common::AlgorithmIdentifier<'_>,
-) -> CryptographyResult<&'p pyo3::PyAny> {
- match &signature_algorithm.params {
- common::AlgorithmParameters::RsaPss(opt_pss) => {
- let pss = opt_pss.as_ref().ok_or_else(|| {
- pyo3::exceptions::PyValueError::new_err("Invalid RSA PSS parameters")
- })?;
- if pss.mask_gen_algorithm.oid != oid::MGF1_OID {
- return Err(CryptographyError::from(
- pyo3::exceptions::PyValueError::new_err(format!(
- "Unsupported mask generation OID: {}",
- pss.mask_gen_algorithm.oid
- )),
- ));
- }
- let py_mask_gen_hash_alg =
- hash_oid_py_hash(py, pss.mask_gen_algorithm.params.oid().clone())?;
- let padding = py.import(pyo3::intern!(
- py,
- "cryptography.hazmat.primitives.asymmetric.padding"
- ))?;
- let py_mgf = padding
- .getattr(pyo3::intern!(py, "MGF1"))?
- .call1((py_mask_gen_hash_alg,))?;
- Ok(padding
- .getattr(pyo3::intern!(py, "PSS"))?
- .call1((py_mgf, pss.salt_length))?)
- }
- common::AlgorithmParameters::RsaWithSha1(_)
- | common::AlgorithmParameters::RsaWithSha1Alt(_)
- | common::AlgorithmParameters::RsaWithSha224(_)
- | common::AlgorithmParameters::RsaWithSha256(_)
- | common::AlgorithmParameters::RsaWithSha384(_)
- | common::AlgorithmParameters::RsaWithSha512(_)
- | common::AlgorithmParameters::RsaWithSha3_224(_)
- | common::AlgorithmParameters::RsaWithSha3_256(_)
- | common::AlgorithmParameters::RsaWithSha3_384(_)
- | common::AlgorithmParameters::RsaWithSha3_512(_) => {
- let pkcs = py
- .import(pyo3::intern!(
- py,
- "cryptography.hazmat.primitives.asymmetric.padding"
- ))?
- .getattr(pyo3::intern!(py, "PKCS1v15"))?
- .call0()?;
- Ok(pkcs)
- }
- common::AlgorithmParameters::EcDsaWithSha224
- | common::AlgorithmParameters::EcDsaWithSha256
- | common::AlgorithmParameters::EcDsaWithSha384
- | common::AlgorithmParameters::EcDsaWithSha512
- | common::AlgorithmParameters::EcDsaWithSha3_224
- | common::AlgorithmParameters::EcDsaWithSha3_256
- | common::AlgorithmParameters::EcDsaWithSha3_384
- | common::AlgorithmParameters::EcDsaWithSha3_512 => {
- let signature_hash_algorithm =
- identify_signature_hash_algorithm(py, signature_algorithm)?;
-
- Ok(py
- .import(pyo3::intern!(
- py,
- "cryptography.hazmat.primitives.asymmetric.ec"
- ))?
- .getattr(pyo3::intern!(py, "ECDSA"))?
- .call1((signature_hash_algorithm,))?)
- }
- _ => Ok(py.None().into_ref(py)),
- }
-}
-
pub(crate) fn add_to_module(module: &pyo3::prelude::PyModule) -> pyo3::PyResult<()> {
module.add_function(pyo3::wrap_pyfunction!(load_der_x509_certificate, module)?)?;
module.add_function(pyo3::wrap_pyfunction!(load_pem_x509_certificate, module)?)?;
diff --git a/src/rust/src/x509/sign.rs b/src/rust/src/x509/sign.rs
index 054300420..16db5a587 100644
--- a/src/rust/src/x509/sign.rs
+++ b/src/rust/src/x509/sign.rs
@@ -2,10 +2,28 @@
// 2.0, and the BSD License. See the LICENSE file in the root of this repository
// for complete details.
+use crate::asn1::oid_to_py_oid;
use crate::error::{CryptographyError, CryptographyResult};
use crate::exceptions;
-use crate::x509::certificate;
use cryptography_x509::{common, oid};
+use once_cell::sync::Lazy;
+use std::collections::HashMap;
+
+// This is similar to a hashmap in ocsp.rs but contains more hash algorithms
+// that aren't allowable in OCSP
+static HASH_OIDS_TO_HASH: Lazy<HashMap<&asn1::ObjectIdentifier, &str>> = Lazy::new(|| {
+ let mut h = HashMap::new();
+ h.insert(&oid::SHA1_OID, "SHA1");
+ h.insert(&oid::SHA224_OID, "SHA224");
+ h.insert(&oid::SHA256_OID, "SHA256");
+ h.insert(&oid::SHA384_OID, "SHA384");
+ h.insert(&oid::SHA512_OID, "SHA512");
+ h.insert(&oid::SHA3_224_OID, "SHA3_224");
+ h.insert(&oid::SHA3_256_OID, "SHA3_256");
+ h.insert(&oid::SHA3_384_OID, "SHA3_384");
+ h.insert(&oid::SHA3_512_OID, "SHA3_512");
+ h
+});
#[derive(Debug, PartialEq)]
pub(crate) enum KeyType {
@@ -368,9 +386,8 @@ pub(crate) fn verify_signature_with_signature_algorithm<'p>(
));
}
let py_signature_algorithm_parameters =
- certificate::identify_signature_algorithm_parameters(py, signature_algorithm)?;
- let py_signature_hash_algorithm =
- certificate::identify_signature_hash_algorithm(py, signature_algorithm)?;
+ identify_signature_algorithm_parameters(py, signature_algorithm)?;
+ let py_signature_hash_algorithm = identify_signature_hash_algorithm(py, signature_algorithm)?;
match key_type {
KeyType::Ed25519 | KeyType::Ed448 => {
issuer_public_key.call_method1(pyo3::intern!(py, "verify"), (signature, data))?
@@ -504,6 +521,124 @@ fn identify_alg_params_for_hash_type(
}
}
+fn hash_oid_py_hash(
+ py: pyo3::Python<'_>,
+ oid: asn1::ObjectIdentifier,
+) -> CryptographyResult<&pyo3::PyAny> {
+ let hashes = py.import(pyo3::intern!(py, "cryptography.hazmat.primitives.hashes"))?;
+ match HASH_OIDS_TO_HASH.get(&oid) {
+ Some(alg_name) => Ok(hashes.getattr(*alg_name)?.call0()?),
+ None => Err(CryptographyError::from(
+ exceptions::UnsupportedAlgorithm::new_err(format!(
+ "Signature algorithm OID: {} not recognized",
+ &oid
+ )),
+ )),
+ }
+}
+
+pub(crate) fn identify_signature_hash_algorithm<'p>(
+ py: pyo3::Python<'p>,
+ signature_algorithm: &common::AlgorithmIdentifier<'_>,
+) -> CryptographyResult<&'p pyo3::PyAny> {
+ let sig_oids_to_hash = py
+ .import(pyo3::intern!(py, "cryptography.hazmat._oid"))?
+ .getattr(pyo3::intern!(py, "_SIG_OIDS_TO_HASH"))?;
+ match &signature_algorithm.params {
+ common::AlgorithmParameters::RsaPss(opt_pss) => {
+ let pss = opt_pss.as_ref().ok_or_else(|| {
+ pyo3::exceptions::PyValueError::new_err("Invalid RSA PSS parameters")
+ })?;
+ hash_oid_py_hash(py, pss.hash_algorithm.oid().clone())
+ }
+ _ => {
+ let py_sig_alg_oid = oid_to_py_oid(py, signature_algorithm.oid())?;
+ let hash_alg = sig_oids_to_hash.get_item(py_sig_alg_oid);
+ match hash_alg {
+ Ok(data) => Ok(data),
+ Err(_) => Err(CryptographyError::from(
+ exceptions::UnsupportedAlgorithm::new_err(format!(
+ "Signature algorithm OID: {} not recognized",
+ signature_algorithm.oid()
+ )),
+ )),
+ }
+ }
+ }
+}
+
+pub(crate) fn identify_signature_algorithm_parameters<'p>(
+ py: pyo3::Python<'p>,
+ signature_algorithm: &common::AlgorithmIdentifier<'_>,
+) -> CryptographyResult<&'p pyo3::PyAny> {
+ match &signature_algorithm.params {
+ common::AlgorithmParameters::RsaPss(opt_pss) => {
+ let pss = opt_pss.as_ref().ok_or_else(|| {
+ pyo3::exceptions::PyValueError::new_err("Invalid RSA PSS parameters")
+ })?;
+ if pss.mask_gen_algorithm.oid != oid::MGF1_OID {
+ return Err(CryptographyError::from(
+ pyo3::exceptions::PyValueError::new_err(format!(
+ "Unsupported mask generation OID: {}",
+ pss.mask_gen_algorithm.oid
+ )),
+ ));
+ }
+ let py_mask_gen_hash_alg =
+ hash_oid_py_hash(py, pss.mask_gen_algorithm.params.oid().clone())?;
+ let padding = py.import(pyo3::intern!(
+ py,
+ "cryptography.hazmat.primitives.asymmetric.padding"
+ ))?;
+ let py_mgf = padding
+ .getattr(pyo3::intern!(py, "MGF1"))?
+ .call1((py_mask_gen_hash_alg,))?;
+ Ok(padding
+ .getattr(pyo3::intern!(py, "PSS"))?
+ .call1((py_mgf, pss.salt_length))?)
+ }
+ common::AlgorithmParameters::RsaWithSha1(_)
+ | common::AlgorithmParameters::RsaWithSha1Alt(_)
+ | common::AlgorithmParameters::RsaWithSha224(_)
+ | common::AlgorithmParameters::RsaWithSha256(_)
+ | common::AlgorithmParameters::RsaWithSha384(_)
+ | common::AlgorithmParameters::RsaWithSha512(_)
+ | common::AlgorithmParameters::RsaWithSha3_224(_)
+ | common::AlgorithmParameters::RsaWithSha3_256(_)
+ | common::AlgorithmParameters::RsaWithSha3_384(_)
+ | common::AlgorithmParameters::RsaWithSha3_512(_) => {
+ let pkcs = py
+ .import(pyo3::intern!(
+ py,
+ "cryptography.hazmat.primitives.asymmetric.padding"
+ ))?
+ .getattr(pyo3::intern!(py, "PKCS1v15"))?
+ .call0()?;
+ Ok(pkcs)
+ }
+ common::AlgorithmParameters::EcDsaWithSha224
+ | common::AlgorithmParameters::EcDsaWithSha256
+ | common::AlgorithmParameters::EcDsaWithSha384
+ | common::AlgorithmParameters::EcDsaWithSha512
+ | common::AlgorithmParameters::EcDsaWithSha3_224
+ | common::AlgorithmParameters::EcDsaWithSha3_256
+ | common::AlgorithmParameters::EcDsaWithSha3_384
+ | common::AlgorithmParameters::EcDsaWithSha3_512 => {
+ let signature_hash_algorithm =
+ identify_signature_hash_algorithm(py, signature_algorithm)?;
+
+ Ok(py
+ .import(pyo3::intern!(
+ py,
+ "cryptography.hazmat.primitives.asymmetric.ec"
+ ))?
+ .getattr(pyo3::intern!(py, "ECDSA"))?
+ .call1((signature_hash_algorithm,))?)
+ }
+ _ => Ok(py.None().into_ref(py)),
+ }
+}
+
#[cfg(test)]
mod tests {
use super::{