Skip to content

Commit 3ee566e

Browse files
committed
Randomness for cryptographic values should come from the cryptographic provider
1 parent 6414d09 commit 3ee566e

File tree

8 files changed

+50
-35
lines changed

8 files changed

+50
-35
lines changed
+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
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+
def get_rand_bytes(size: int) -> bytes: ...

Diff for: src/rust/src/backend/aead.rs

+15-14
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) {
@@ -533,8 +533,10 @@ impl ChaCha20Poly1305 {
533533
}
534534

535535
#[staticmethod]
536-
fn generate_key(py: pyo3::Python<'_>) -> CryptographyResult<pyo3::Bound<'_, pyo3::PyAny>> {
537-
Ok(types::OS_URANDOM.get(py)?.call1((32,))?)
536+
fn generate_key(
537+
py: pyo3::Python<'_>,
538+
) -> CryptographyResult<pyo3::Bound<'_, pyo3::types::PyBytes>> {
539+
crate::backend::rand::get_rand_bytes(py, 32)
538540
}
539541

540542
#[pyo3(signature = (nonce, data, associated_data))]
@@ -644,14 +646,14 @@ impl AesGcm {
644646
fn generate_key(
645647
py: pyo3::Python<'_>,
646648
bit_length: usize,
647-
) -> CryptographyResult<pyo3::Bound<'_, pyo3::PyAny>> {
649+
) -> CryptographyResult<pyo3::Bound<'_, pyo3::types::PyBytes>> {
648650
if bit_length != 128 && bit_length != 192 && bit_length != 256 {
649651
return Err(CryptographyError::from(
650652
pyo3::exceptions::PyValueError::new_err("bit_length must be 128, 192, or 256"),
651653
));
652654
}
653655

654-
Ok(types::OS_URANDOM.get(py)?.call1((bit_length / 8,))?)
656+
crate::backend::rand::get_rand_bytes(py, bit_length / 8)
655657
}
656658

657659
#[pyo3(signature = (nonce, data, associated_data))]
@@ -760,14 +762,13 @@ impl AesCcm {
760762
fn generate_key(
761763
py: pyo3::Python<'_>,
762764
bit_length: usize,
763-
) -> CryptographyResult<pyo3::Bound<'_, pyo3::PyAny>> {
765+
) -> CryptographyResult<pyo3::Bound<'_, pyo3::types::PyBytes>> {
764766
if bit_length != 128 && bit_length != 192 && bit_length != 256 {
765767
return Err(CryptographyError::from(
766768
pyo3::exceptions::PyValueError::new_err("bit_length must be 128, 192, or 256"),
767769
));
768770
}
769-
770-
Ok(types::OS_URANDOM.get(py)?.call1((bit_length / 8,))?)
771+
crate::backend::rand::get_rand_bytes(py, bit_length / 8)
771772
}
772773

773774
#[pyo3(signature = (nonce, data, associated_data))]
@@ -896,14 +897,14 @@ impl AesSiv {
896897
fn generate_key(
897898
py: pyo3::Python<'_>,
898899
bit_length: usize,
899-
) -> CryptographyResult<pyo3::Bound<'_, pyo3::PyAny>> {
900+
) -> CryptographyResult<pyo3::Bound<'_, pyo3::types::PyBytes>> {
900901
if bit_length != 256 && bit_length != 384 && bit_length != 512 {
901902
return Err(CryptographyError::from(
902903
pyo3::exceptions::PyValueError::new_err("bit_length must be 256, 384, or 512"),
903904
));
904905
}
905906

906-
Ok(types::OS_URANDOM.get(py)?.call1((bit_length / 8,))?)
907+
crate::backend::rand::get_rand_bytes(py, bit_length / 8)
907908
}
908909

909910
#[pyo3(signature = (data, associated_data))]
@@ -994,14 +995,14 @@ impl AesOcb3 {
994995
fn generate_key(
995996
py: pyo3::Python<'_>,
996997
bit_length: usize,
997-
) -> CryptographyResult<pyo3::Bound<'_, pyo3::PyAny>> {
998+
) -> CryptographyResult<pyo3::Bound<'_, pyo3::types::PyBytes>> {
998999
if bit_length != 128 && bit_length != 192 && bit_length != 256 {
9991000
return Err(CryptographyError::from(
10001001
pyo3::exceptions::PyValueError::new_err("bit_length must be 128, 192, or 256"),
10011002
));
10021003
}
10031004

1004-
Ok(types::OS_URANDOM.get(py)?.call1((bit_length / 8,))?)
1005+
crate::backend::rand::get_rand_bytes(py, bit_length / 8)
10051006
}
10061007

10071008
#[pyo3(signature = (nonce, data, associated_data))]
@@ -1121,14 +1122,14 @@ impl AesGcmSiv {
11211122
fn generate_key(
11221123
py: pyo3::Python<'_>,
11231124
bit_length: usize,
1124-
) -> CryptographyResult<pyo3::Bound<'_, pyo3::PyAny>> {
1125+
) -> CryptographyResult<pyo3::Bound<'_, pyo3::types::PyBytes>> {
11251126
if bit_length != 128 && bit_length != 192 && bit_length != 256 {
11261127
return Err(CryptographyError::from(
11271128
pyo3::exceptions::PyValueError::new_err("bit_length must be 128, 192, or 256"),
11281129
));
11291130
}
11301131

1131-
Ok(types::OS_URANDOM.get(py)?.call1((bit_length / 8,))?)
1132+
crate::backend::rand::get_rand_bytes(py, bit_length / 8)
11321133
}
11331134

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

Diff for: src/rust/src/backend/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub(crate) mod hmac;
1717
pub(crate) mod kdf;
1818
pub(crate) mod keys;
1919
pub(crate) mod poly1305;
20+
pub(crate) mod rand;
2021
pub(crate) mod rsa;
2122
pub(crate) mod utils;
2223
pub(crate) mod x25519;

Diff for: src/rust/src/backend/rand.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
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+
#[pyo3::pyfunction]
8+
pub(crate) fn get_rand_bytes(
9+
py: pyo3::Python<'_>,
10+
size: usize,
11+
) -> CryptographyResult<pyo3::Bound<'_, pyo3::types::PyBytes>> {
12+
Ok(pyo3::types::PyBytes::new_with(py, len, |b| {
13+
#[cfg(any(CRYPTOGRAPHY_IS_LIBRESSL, CRYPTOGRAPHY_IS_BORINGSSL))]
14+
openssl::rand::rand_bytes(b).map_err(CryptographyError::from)?;
15+
#[cfg(not(any(CRYPTOGRAPHY_IS_LIBRESSL, CRYPTOGRAPHY_IS_BORINGSSL)))]
16+
openssl::rand::rand_priv_bytes(b).map_err(CryptographyError::from)?;
17+
Ok(())
18+
})?)
19+
}

Diff for: src/rust/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,8 @@ mod _rust {
191191
#[pymodule_export]
192192
use crate::backend::poly1305::poly1305;
193193
#[pymodule_export]
194+
use crate::backend::rand::get_rand_bytes;
195+
#[pymodule_export]
194196
use crate::backend::rsa::rsa;
195197
#[pymodule_export]
196198
use crate::backend::x25519::x25519;

Diff for: src/rust/src/pkcs12.rs

+6-16
Original file line numberDiff line numberDiff line change
@@ -418,13 +418,9 @@ fn serialize_bags<'p>(
418418
if !plain_safebags.is_empty() {
419419
plain_safebag_contents =
420420
asn1::write_single(&asn1::SequenceOfWriter::new(plain_safebags))?;
421-
auth_safe_salt = types::OS_URANDOM
422-
.get(py)?
423-
.call1((e.salt_length(),))?
421+
auth_safe_salt = crate::backend::rand::get_rand_bytes(py, e.salt_length())?
424422
.extract::<pyo3::pybacked::PyBackedBytes>()?;
425-
auth_safe_iv = types::OS_URANDOM
426-
.get(py)?
427-
.call1((16,))?
423+
auth_safe_iv = crate::backend::rand::get_rand_bytes(py, 16)?
428424
.extract::<pyo3::pybacked::PyBackedBytes>()?;
429425
auth_safe_ciphertext = e.encrypt(
430426
py,
@@ -475,10 +471,8 @@ fn serialize_bags<'p>(
475471

476472
let auth_safe_content = asn1::write_single(&asn1::SequenceOfWriter::new(auth_safe_contents))?;
477473

478-
let salt = types::OS_URANDOM
479-
.get(py)?
480-
.call1((8,))?
481-
.extract::<pyo3::pybacked::PyBackedBytes>()?;
474+
let salt =
475+
crate::backend::rand::get_rand_bytes(py, 8)?.extract::<pyo3::pybacked::PyBackedBytes>()?;
482476
let mac_algorithm_md =
483477
hashes::message_digest_from_algorithm(py, &encryption_details.mac_algorithm)?;
484478
let mac_key = cryptography_crypto::pkcs12::kdf(
@@ -596,13 +590,9 @@ fn serialize_key_and_certificates<'p>(
596590
.extract::<pyo3::pybacked::PyBackedBytes>()?;
597591

598592
let key_bag = if let Some(ref e) = encryption_details.encryption_algorithm {
599-
key_salt = types::OS_URANDOM
600-
.get(py)?
601-
.call1((e.salt_length(),))?
593+
key_salt = crate::backend::rand::get_rand_bytes(py, e.salt_length())?
602594
.extract::<pyo3::pybacked::PyBackedBytes>()?;
603-
key_iv = types::OS_URANDOM
604-
.get(py)?
605-
.call1((16,))?
595+
key_iv = crate::backend::rand::get_rand_bytes(py, 16)?
606596
.extract::<pyo3::pybacked::PyBackedBytes>()?;
607597
key_ciphertext = e.encrypt(
608598
py,

Diff for: src/rust/src/pkcs7.rs

+2-4
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(

Diff for: src/rust/src/types.rs

-1
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)