Skip to content

Commit 50cd3d8

Browse files
authored
Randomness for cryptographic values should come from the cryptographic provider (#12688)
* Randomness for cryptographic values should come from the cryptographic provider * Don't export function to python per feedback
1 parent 5cbd0b1 commit 50cd3d8

File tree

6 files changed

+50
-35
lines changed

6 files changed

+50
-35
lines changed

src/rust/src/backend/aead.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use pyo3::types::{PyAnyMethods, PyListMethods};
66

77
use crate::buf::CffiBuf;
88
use crate::error::{CryptographyError, CryptographyResult};
9-
use crate::{exceptions, types};
9+
use crate::exceptions;
1010

1111
fn check_length(data: &[u8]) -> CryptographyResult<()> {
1212
if data.len() > (i32::MAX as usize) {
@@ -525,8 +525,10 @@ impl ChaCha20Poly1305 {
525525
}
526526

527527
#[staticmethod]
528-
fn generate_key(py: pyo3::Python<'_>) -> CryptographyResult<pyo3::Bound<'_, pyo3::PyAny>> {
529-
Ok(types::OS_URANDOM.get(py)?.call1((32,))?)
528+
fn generate_key(
529+
py: pyo3::Python<'_>,
530+
) -> CryptographyResult<pyo3::Bound<'_, pyo3::types::PyBytes>> {
531+
crate::backend::rand::get_rand_bytes(py, 32)
530532
}
531533

532534
#[pyo3(signature = (nonce, data, associated_data))]
@@ -639,14 +641,14 @@ impl AesGcm {
639641
fn generate_key(
640642
py: pyo3::Python<'_>,
641643
bit_length: usize,
642-
) -> CryptographyResult<pyo3::Bound<'_, pyo3::PyAny>> {
644+
) -> CryptographyResult<pyo3::Bound<'_, pyo3::types::PyBytes>> {
643645
if bit_length != 128 && bit_length != 192 && bit_length != 256 {
644646
return Err(CryptographyError::from(
645647
pyo3::exceptions::PyValueError::new_err("bit_length must be 128, 192, or 256"),
646648
));
647649
}
648650

649-
Ok(types::OS_URANDOM.get(py)?.call1((bit_length / 8,))?)
651+
crate::backend::rand::get_rand_bytes(py, bit_length / 8)
650652
}
651653

652654
#[pyo3(signature = (nonce, data, associated_data))]
@@ -755,14 +757,13 @@ impl AesCcm {
755757
fn generate_key(
756758
py: pyo3::Python<'_>,
757759
bit_length: usize,
758-
) -> CryptographyResult<pyo3::Bound<'_, pyo3::PyAny>> {
760+
) -> CryptographyResult<pyo3::Bound<'_, pyo3::types::PyBytes>> {
759761
if bit_length != 128 && bit_length != 192 && bit_length != 256 {
760762
return Err(CryptographyError::from(
761763
pyo3::exceptions::PyValueError::new_err("bit_length must be 128, 192, or 256"),
762764
));
763765
}
764-
765-
Ok(types::OS_URANDOM.get(py)?.call1((bit_length / 8,))?)
766+
crate::backend::rand::get_rand_bytes(py, bit_length / 8)
766767
}
767768

768769
#[pyo3(signature = (nonce, data, associated_data))]
@@ -891,14 +892,14 @@ impl AesSiv {
891892
fn generate_key(
892893
py: pyo3::Python<'_>,
893894
bit_length: usize,
894-
) -> CryptographyResult<pyo3::Bound<'_, pyo3::PyAny>> {
895+
) -> CryptographyResult<pyo3::Bound<'_, pyo3::types::PyBytes>> {
895896
if bit_length != 256 && bit_length != 384 && bit_length != 512 {
896897
return Err(CryptographyError::from(
897898
pyo3::exceptions::PyValueError::new_err("bit_length must be 256, 384, or 512"),
898899
));
899900
}
900901

901-
Ok(types::OS_URANDOM.get(py)?.call1((bit_length / 8,))?)
902+
crate::backend::rand::get_rand_bytes(py, bit_length / 8)
902903
}
903904

904905
#[pyo3(signature = (data, associated_data))]
@@ -989,14 +990,14 @@ impl AesOcb3 {
989990
fn generate_key(
990991
py: pyo3::Python<'_>,
991992
bit_length: usize,
992-
) -> CryptographyResult<pyo3::Bound<'_, pyo3::PyAny>> {
993+
) -> CryptographyResult<pyo3::Bound<'_, pyo3::types::PyBytes>> {
993994
if bit_length != 128 && bit_length != 192 && bit_length != 256 {
994995
return Err(CryptographyError::from(
995996
pyo3::exceptions::PyValueError::new_err("bit_length must be 128, 192, or 256"),
996997
));
997998
}
998999

999-
Ok(types::OS_URANDOM.get(py)?.call1((bit_length / 8,))?)
1000+
crate::backend::rand::get_rand_bytes(py, bit_length / 8)
10001001
}
10011002

10021003
#[pyo3(signature = (nonce, data, associated_data))]
@@ -1116,14 +1117,14 @@ impl AesGcmSiv {
11161117
fn generate_key(
11171118
py: pyo3::Python<'_>,
11181119
bit_length: usize,
1119-
) -> CryptographyResult<pyo3::Bound<'_, pyo3::PyAny>> {
1120+
) -> CryptographyResult<pyo3::Bound<'_, pyo3::types::PyBytes>> {
11201121
if bit_length != 128 && bit_length != 192 && bit_length != 256 {
11211122
return Err(CryptographyError::from(
11221123
pyo3::exceptions::PyValueError::new_err("bit_length must be 128, 192, or 256"),
11231124
));
11241125
}
11251126

1126-
Ok(types::OS_URANDOM.get(py)?.call1((bit_length / 8,))?)
1127+
crate::backend::rand::get_rand_bytes(py, bit_length / 8)
11271128
}
11281129

11291130
#[pyo3(signature = (nonce, data, associated_data))]

src/rust/src/backend/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub(crate) mod hmac;
2121
pub(crate) mod kdf;
2222
pub(crate) mod keys;
2323
pub(crate) mod poly1305;
24+
pub(crate) mod rand;
2425
pub(crate) mod rsa;
2526
pub(crate) mod utils;
2627
pub(crate) mod x25519;

src/rust/src/backend/rand.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// This file is dual licensed under the terms of the Apache License, Version
2+
// 2.0, and the BSD License. See the LICENSE file in the root of this repository
3+
// for complete details.
4+
5+
use crate::error::{CryptographyError, CryptographyResult};
6+
7+
pub(crate) fn get_rand_bytes(
8+
py: pyo3::Python<'_>,
9+
size: usize,
10+
) -> CryptographyResult<pyo3::Bound<'_, pyo3::types::PyBytes>> {
11+
Ok(pyo3::types::PyBytes::new_with(py, size, |b| {
12+
#[cfg(any(
13+
CRYPTOGRAPHY_IS_LIBRESSL,
14+
CRYPTOGRAPHY_IS_BORINGSSL,
15+
CRYPTOGRAPHY_IS_AWSLC
16+
))]
17+
openssl::rand::rand_bytes(b).map_err(CryptographyError::from)?;
18+
#[cfg(not(any(
19+
CRYPTOGRAPHY_IS_LIBRESSL,
20+
CRYPTOGRAPHY_IS_BORINGSSL,
21+
CRYPTOGRAPHY_IS_AWSLC
22+
)))]
23+
openssl::rand::rand_priv_bytes(b).map_err(CryptographyError::from)?;
24+
Ok(())
25+
})?)
26+
}

src/rust/src/pkcs12.rs

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -432,13 +432,9 @@ fn serialize_safebags<'p>(
432432
if !plain_safebags.is_empty() {
433433
plain_safebag_contents =
434434
asn1::write_single(&asn1::SequenceOfWriter::new(plain_safebags))?;
435-
auth_safe_salt = types::OS_URANDOM
436-
.get(py)?
437-
.call1((e.salt_length(),))?
435+
auth_safe_salt = crate::backend::rand::get_rand_bytes(py, e.salt_length())?
438436
.extract::<pyo3::pybacked::PyBackedBytes>()?;
439-
auth_safe_iv = types::OS_URANDOM
440-
.get(py)?
441-
.call1((16,))?
437+
auth_safe_iv = crate::backend::rand::get_rand_bytes(py, 16)?
442438
.extract::<pyo3::pybacked::PyBackedBytes>()?;
443439
auth_safe_ciphertext = e.encrypt(
444440
py,
@@ -489,10 +485,8 @@ fn serialize_safebags<'p>(
489485

490486
let auth_safe_content = asn1::write_single(&asn1::SequenceOfWriter::new(auth_safe_contents))?;
491487

492-
let salt = types::OS_URANDOM
493-
.get(py)?
494-
.call1((8,))?
495-
.extract::<pyo3::pybacked::PyBackedBytes>()?;
488+
let salt =
489+
crate::backend::rand::get_rand_bytes(py, 8)?.extract::<pyo3::pybacked::PyBackedBytes>()?;
496490
let mac_algorithm_md =
497491
hashes::message_digest_from_algorithm(py, &encryption_details.mac_algorithm)?;
498492
let mac_key = cryptography_crypto::pkcs12::kdf(
@@ -634,13 +628,9 @@ fn serialize_key_and_certificates<'p>(
634628
.extract::<pyo3::pybacked::PyBackedBytes>()?;
635629

636630
let key_bag = if let Some(ref e) = encryption_details.encryption_algorithm {
637-
key_salt = types::OS_URANDOM
638-
.get(py)?
639-
.call1((e.salt_length(),))?
631+
key_salt = crate::backend::rand::get_rand_bytes(py, e.salt_length())?
640632
.extract::<pyo3::pybacked::PyBackedBytes>()?;
641-
key_iv = types::OS_URANDOM
642-
.get(py)?
643-
.call1((16,))?
633+
key_iv = crate::backend::rand::get_rand_bytes(py, 16)?
644634
.extract::<pyo3::pybacked::PyBackedBytes>()?;
645635
key_ciphertext = e.encrypt(
646636
py,

src/rust/src/pkcs7.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,11 @@ fn encrypt_and_serialize<'p>(
103103
// Get the content encryption algorithm
104104
let content_encryption_algorithm_type = content_encryption_algorithm;
105105
let key_size = content_encryption_algorithm_type.getattr(pyo3::intern!(py, "key_size"))?;
106-
let key = types::OS_URANDOM
107-
.get(py)?
108-
.call1((key_size.floor_div(8)?,))?;
106+
let key = crate::backend::rand::get_rand_bytes(py, key_size.floor_div(8)?.extract()?)?;
109107
let content_encryption_algorithm = content_encryption_algorithm_type.call1((&key,))?;
110108

111109
// Get the mode
112-
let iv = types::OS_URANDOM.get(py)?.call1((16,))?;
110+
let iv = crate::backend::rand::get_rand_bytes(py, 16)?;
113111
let cbc_mode = types::CBC.get(py)?.call1((&iv,))?;
114112

115113
let encrypted_content = symmetric_encrypt(

src/rust/src/types.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ pub static DATETIME_TIMEZONE_UTC: LazyPyImport =
3737
LazyPyImport::new("datetime", &["timezone", "utc"]);
3838
pub static IPADDRESS_IPADDRESS: LazyPyImport = LazyPyImport::new("ipaddress", &["ip_address"]);
3939
pub static IPADDRESS_IPNETWORK: LazyPyImport = LazyPyImport::new("ipaddress", &["ip_network"]);
40-
pub static OS_URANDOM: LazyPyImport = LazyPyImport::new("os", &["urandom"]);
4140

4241
pub static DEPRECATED_IN_36: LazyPyImport =
4342
LazyPyImport::new("cryptography.utils", &["DeprecatedIn36"]);

0 commit comments

Comments
 (0)