Introduce a keepalive abstraction (#10764)

This effectively emulates what pyo3's old GIL pool was doing, but we'll use it in a far more targetted manner.
This commit is contained in:
Alex Gaynor 2024-04-12 13:47:15 -04:00 committed by GitHub
parent 1d04970f37
commit 0acc56b7d4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 65 additions and 10 deletions

5
src/rust/Cargo.lock generated
View file

@ -67,6 +67,10 @@ dependencies = [
"pyo3",
]
[[package]]
name = "cryptography-keepalive"
version = "0.1.0"
[[package]]
name = "cryptography-key-parsing"
version = "0.1.0"
@ -96,6 +100,7 @@ dependencies = [
"asn1",
"cfg-if",
"cryptography-cffi",
"cryptography-keepalive",
"cryptography-key-parsing",
"cryptography-openssl",
"cryptography-x509",

View file

@ -13,6 +13,7 @@ cfg-if = "1"
pyo3 = { version = "0.21.1", features = ["abi3", "gil-refs"] }
asn1 = { version = "0.16.1", default-features = false }
cryptography-cffi = { path = "cryptography-cffi" }
cryptography-keepalive = { path = "cryptography-keepalive" }
cryptography-key-parsing = { path = "cryptography-key-parsing" }
cryptography-x509 = { path = "cryptography-x509" }
cryptography-x509-verification = { path = "cryptography-x509-verification" }
@ -37,6 +38,7 @@ overflow-checks = true
[workspace]
members = [
"cryptography-cffi",
"cryptography-keepalive",
"cryptography-key-parsing",
"cryptography-openssl",
"cryptography-x509",

View file

@ -0,0 +1,10 @@
[package]
name = "cryptography-keepalive"
version = "0.1.0"
authors = ["The cryptography developers <cryptography-dev@python.org>"]
edition = "2021"
publish = false
# This specifies the MSRV
rust-version = "1.65.0"
[dependencies]

View file

@ -0,0 +1,40 @@
// This file is dual licensed under the terms of the Apache License, Version
// 2.0, and the BSD License. See the LICENSE file in the root of this repository
// for complete details.
#![deny(rust_2018_idioms, clippy::undocumented_unsafe_blocks)]
use std::cell::UnsafeCell;
use std::ops::Deref;
pub struct KeepAlive<T: StableDeref> {
values: UnsafeCell<Vec<T>>,
}
/// # Safety
/// Implementors of this trait must ensure that the value returned by
/// `deref()` must remain valid, even if `self` is moved.
pub unsafe trait StableDeref: Deref {}
// SAFETY: `Vec`'s data is on the heap, so as long as it's not mutated, the
// slice returned by `deref` remains valid.
unsafe impl<T> StableDeref for Vec<T> {}
#[allow(clippy::new_without_default)]
impl<T: StableDeref> KeepAlive<T> {
pub fn new() -> Self {
KeepAlive {
values: UnsafeCell::new(vec![]),
}
}
pub fn add(&self, v: T) -> &T::Target {
// SAFETY: We only ever append to `self.values`, which, when combined
// with the invariants of `StableDeref`, means that the result of
// `deref()` will always be valid for the lifetime of `&self`.
unsafe {
let values = &mut *self.values.get();
values.push(v);
values.last().unwrap().deref()
}
}
}

View file

@ -129,15 +129,8 @@ fn sign_and_serialize<'p>(
.map(|p| p.raw.borrow_dependent())
.collect::<Vec<_>>();
let mut digests = vec![];
if !options.contains(&types::PKCS7_NO_ATTRIBUTES.get_bound(py)?)? {
for (_, _, py_hash_alg, _) in &py_signers {
let digest =
asn1::write_single(&x509::ocsp::hash_data(py, py_hash_alg, &data_with_header)?)?;
digests.push(digest);
}
}
for (i, (cert, py_private_key, py_hash_alg, rsa_padding)) in py_signers.iter().enumerate() {
let ka = cryptography_keepalive::KeepAlive::new();
for (cert, py_private_key, py_hash_alg, rsa_padding) in py_signers.iter() {
let (authenticated_attrs, signature) =
if options.contains(&types::PKCS7_NO_ATTRIBUTES.get_bound(py)?)? {
(
@ -166,10 +159,15 @@ fn sign_and_serialize<'p>(
},
];
let digest = ka.add(asn1::write_single(&x509::ocsp::hash_data(
py,
py_hash_alg,
&data_with_header,
)?)?);
authenticated_attrs.push(Attribute {
type_id: PKCS7_MESSAGE_DIGEST_OID,
values: common::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new([
asn1::parse_single(&digests[i]).unwrap(),
asn1::parse_single(digest).unwrap(),
])),
});