Skip to content

Commit cefad3d

Browse files
committed
Add the no_heap feature to disable heap-using functionality.
The RSA doctest had to be disabled temporarily until rust-lang/rust#30372 makes it to the stable Rust channel (Rust 1.8). Some of the tests and the test framework in |ring::file_test| are still using the heap. This will be fixed separately.
1 parent eafc859 commit cefad3d

File tree

7 files changed

+83
-5
lines changed

7 files changed

+83
-5
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ branch = "optional-rand-rustc_serialize"
2323
default-features = false
2424
features = ["bigint"]
2525

26+
[features]
27+
# These features are documented in the top-level module's documentation.
28+
no_heap = []
29+
2630
# Fix the `bench`, `release`, and `test` profiles so they all have the
2731
# same configuration.
2832
#

src/agreement.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,30 @@
1414

1515
//! Key agreement: ECDH.
1616
17-
use super::{c, digest, ecc, ffi};
18-
use super::input::Input;
1917
use std;
18+
use super::{c, digest, ecc};
19+
#[cfg(not(feature = "no_heap"))] use super::ffi;
20+
use super::input::Input;
2021

2122
/// A key agreement algorithm.
2223
pub struct Algorithm {
24+
#[cfg_attr(feature = "no_heap", allow(dead_code))]
2325
ec_group_fn: unsafe extern fn () -> *const ecc::EC_GROUP,
26+
2427
encoded_public_key_len: usize,
28+
29+
#[cfg_attr(feature = "no_heap", allow(dead_code))]
2530
nid: c::int,
31+
2632
generate_key_pair: fn(alg: &'static Algorithm) -> Result<KeyPairImpl, ()>,
33+
2734
fill_with_public_key: fn(algorithm: &Algorithm, key_pair_impl: &KeyPairImpl,
2835
out: &mut [u8]) -> Result<(), ()>,
36+
2937
agree: fn(key_pair: &KeyPairImpl, peer_public_key_pair_alg: &Algorithm,
3038
peer_public_key: &[u8], shared_key: &mut [u8])
3139
-> Result<usize, ()>,
40+
3241
drop_key_pair: fn(key_pair_impl: &mut KeyPairImpl),
3342
}
3443

@@ -83,6 +92,7 @@ impl Drop for EphemeralKeyPair {
8392
}
8493

8594
enum KeyPairImpl {
95+
#[cfg(not(feature = "no_heap"))]
8696
NIST {
8797
key: *mut EC_KEY,
8898
},
@@ -191,6 +201,7 @@ pub extern fn SHA512_5(out: *mut u8, out_len: c::size_t,
191201

192202
macro_rules! nist_ecdh {
193203
( $NAME:ident, $bits:expr, $name_str:expr, $ec_group_fn:expr, $nid:expr ) => {
204+
#[cfg(not(feature = "no_heap"))]
194205
#[doc="ECDH using the NIST"]
195206
#[doc=$name_str]
196207
#[doc="curve."]
@@ -212,6 +223,8 @@ macro_rules! nist_ecdh {
212223
/// reduced modulo *q* are currently reduced mod *q* during
213224
/// verification. Soon, coordinates larger than *q* - 1 will be
214225
/// rejected.
226+
///
227+
/// Not available in `no_heap` mode.
215228
pub static $NAME: Algorithm = Algorithm {
216229
ec_group_fn: $ec_group_fn,
217230
encoded_public_key_len: 1 + (2 * (($bits + 7) / 8)),
@@ -231,13 +244,15 @@ nist_ecdh!(ECDH_P384, 384, "P-384 (secp256r1)", ecc::EC_GROUP_P384,
231244
nist_ecdh!(ECDH_P521, 521, "P-521 (secp256r1)", ecc::EC_GROUP_P521,
232245
716 /*NID_secp521r1*/);
233246

247+
#[cfg(not(feature = "no_heap"))]
234248
fn nist_ecdh_generate_key_pair(algorithm: &Algorithm) -> Result<KeyPairImpl, ()> {
235249
let key = try!(ffi::map_bssl_ptr_result(unsafe {
236250
EC_KEY_generate_key_ex((algorithm.ec_group_fn)())
237251
}));
238252
Ok(KeyPairImpl::NIST { key: key })
239253
}
240254

255+
#[cfg(not(feature = "no_heap"))]
241256
fn nist_ecdh_fill_with_public_key(algorithm: &Algorithm,
242257
key_pair_impl: &KeyPairImpl, out: &mut [u8])
243258
-> Result<(), ()> {
@@ -253,6 +268,7 @@ fn nist_ecdh_fill_with_public_key(algorithm: &Algorithm,
253268
}
254269
}
255270

271+
#[cfg(not(feature = "no_heap"))]
256272
fn nist_ecdh_agree(key_pair_impl: &KeyPairImpl, peer_public_key_alg: &Algorithm,
257273
peer_public_key: &[u8], shared_key: &mut [u8])
258274
-> Result<usize, ()> {
@@ -270,6 +286,7 @@ fn nist_ecdh_agree(key_pair_impl: &KeyPairImpl, peer_public_key_alg: &Algorithm,
270286
}
271287
}
272288

289+
#[cfg(not(feature = "no_heap"))]
273290
fn nist_ecdh_drop_key_pair(key_pair_impl: &mut KeyPairImpl) {
274291
match key_pair_impl {
275292
&mut KeyPairImpl::NIST { key } => {
@@ -280,15 +297,22 @@ fn nist_ecdh_drop_key_pair(key_pair_impl: &mut KeyPairImpl) {
280297
}
281298
}
282299

300+
#[cfg(not(feature = "no_heap"))]
283301
#[allow(non_camel_case_types)]
284302
enum EC_KEY { }
285303

286304
extern {
305+
#[cfg(not(feature = "no_heap"))]
287306
fn EC_KEY_generate_key_ex(group: *const ecc::EC_GROUP) -> *mut EC_KEY;
307+
308+
#[cfg(not(feature = "no_heap"))]
288309
fn EC_KEY_public_key_to_oct(key: *const EC_KEY, out: *mut u8,
289310
out_len: c::size_t) -> c::size_t;
311+
312+
#[cfg(not(feature = "no_heap"))]
290313
fn EC_KEY_free(key: *mut EC_KEY);
291314

315+
#[cfg(not(feature = "no_heap"))]
292316
fn ECDH_compute_key_ex(out: *mut u8, out_len: *mut c::size_t,
293317
max_out_len: c::size_t, my_key_pair: *const EC_KEY,
294318
peer_curve_nid: c::int,

src/ecc.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#[allow(non_camel_case_types)]
1616
pub enum EC_GROUP { }
1717

18+
#[cfg(not(feature = "no_heap"))]
1819
extern {
1920
pub fn EC_GROUP_P256() -> *const EC_GROUP;
2021
pub fn EC_GROUP_P384() -> *const EC_GROUP;

src/exe_tests.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,27 @@ macro_rules! exe_test {
3535
}
3636

3737
exe_test!(aes_test, "crypto/aes/aes_test", []);
38+
39+
#[cfg(not(feature = "no_heap"))]
3840
exe_test!(bn_test, "crypto/bn/bn_test", []);
41+
42+
#[cfg(not(feature = "no_heap"))]
3943
exe_test!(bytestring_test, "crypto/bytestring/bytestring_test", []);
44+
4045
exe_test!(constant_time_test, "crypto/constant_time_test", []);
46+
47+
#[cfg(not(feature = "no_heap"))]
4148
exe_test!(ecdsa_test, "crypto/ecdsa/ecdsa_test", []);
49+
4250
exe_test!(gcm_test, "crypto/modes/gcm_test", []);
43-
exe_test!(poly1305_test, "crypto/poly1305/poly1305_test", ["crypto/poly1305/poly1305_test.txt"]);
51+
52+
#[cfg(not(feature = "no_heap"))] // XXX: Rewrite to avoid OPENSSL_malloc
53+
exe_test!(poly1305_test, "crypto/poly1305/poly1305_test",
54+
["crypto/poly1305/poly1305_test.txt"]);
55+
4456
exe_test!(refcount_test, "crypto/refcount_test", []);
57+
58+
#[cfg(not(feature = "no_heap"))]
4559
exe_test!(rsa_test, "crypto/rsa/rsa_test", []);
60+
4661
exe_test!(thread_test, "crypto/thread_test", []);

src/ffi.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub fn map_bssl_result(bssl_result: c::int) -> Result<(), ()> {
2121
}
2222
}
2323

24+
#[cfg(not(feature = "no_heap"))]
2425
pub fn map_bssl_ptr_result<T>(bssl_result: *mut T) -> Result<*mut T, ()> {
2526
if bssl_result.is_null() {
2627
return Err(());

src/lib.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,22 @@
1212
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1313
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1414

15+
//! Safe, fast, small crypto using Rust with BoringSSL's cryptography primitives.
16+
//!
17+
//! # Feature Flags
18+
//!
19+
//! <table>
20+
//! <tr><th>Feature
21+
//! <th>Description
22+
//! <tr><td><code>no_heap</code>
23+
//! <td>Disable all functionality that uses the heap. This is useful for
24+
//! code running in kernel space and some embedded applications. The
25+
//! goal is to enable as much functionality as is practical in
26+
//! <code>no_heap</code> mode, but for now some RSA, ECDH, and ECDSA
27+
//! functionality still uses the heap.
28+
//! </table>
29+
30+
1531
#[cfg(test)]
1632
extern crate rustc_serialize;
1733

src/signature.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@
3636
//! larger messages will be added later. Similarly, the signing interface is
3737
//! not available yet.
3838
39-
use super::{c, digest, ecc, ffi};
39+
use super::{c, ffi};
40+
#[cfg(not(feature = "no_heap"))] use super::{digest, ecc};
4041
use super::input::Input;
4142

4243
/// A signature verification algorithm.
@@ -70,13 +71,17 @@ trait VerificationAlgorithmImpl {
7071
///
7172
/// ## Verify a RSA PKCS#1 signature that uses the SHA-256 digest
7273
///
73-
/// ```
74+
/// ```ignore
75+
/// # // XXX: Re-enable when https://github.com/rust-lang/rust/pull/30372
76+
/// # // reaches stable.
77+
/// #
7478
/// use ring::input::Input;
7579
/// use ring::signature;
7680
///
7781
/// // Ideally this function should take its inputs as `Input`s instead of
7882
/// // slices. It takes its input as slices to illustrate how to convert slices
7983
/// // to `Input`s.
84+
/// # #[cfg(not(feature = "no_heap"))]
8085
/// fn verify_rsa_pkcs1_sha256(public_key: &[u8], msg: &[u8], sig: &[u8])
8186
/// -> Result<(), ()> {
8287
/// let public_key = try!(Input::new(public_key));
@@ -105,11 +110,13 @@ pub fn verify(alg: &VerificationAlgorithm, public_key: Input, msg: Input,
105110

106111

107112
/// ECDSA Signatures.
113+
#[cfg(not(feature = "no_heap"))]
108114
struct ECDSA {
109115
digest_alg: &'static digest::Algorithm,
110116
ec_group_fn: unsafe extern fn() -> *const ecc::EC_GROUP,
111117
}
112118

119+
#[cfg(not(feature = "no_heap"))]
113120
impl VerificationAlgorithmImpl for ECDSA {
114121
fn verify(&self, public_key: Input, msg: Input, signature: Input)
115122
-> Result<(), ()> {
@@ -130,6 +137,7 @@ impl VerificationAlgorithmImpl for ECDSA {
130137
macro_rules! ecdsa {
131138
( $VERIFY_ALGORITHM:ident, $curve_name:expr, $ec_group_fn:expr,
132139
$digest_alg_name:expr, $digest_alg:expr ) => {
140+
#[cfg(not(feature = "no_heap"))]
133141
#[doc="ECDSA signatures using the "]
134142
#[doc=$curve_name]
135143
#[doc=" curve and the "]
@@ -158,6 +166,8 @@ macro_rules! ecdsa {
158166
/// described in [RFC 3279 Section
159167
/// 2.2.3](https://tools.ietf.org/html/rfc3279#section-2.2.3). Both *r*
160168
/// and *s* are verified to be in the range [1, *n* - 1].
169+
///
170+
/// Not available in `no_heap` mode.
161171
pub static $VERIFY_ALGORITHM: VerificationAlgorithm =
162172
VerificationAlgorithm {
163173
implementation: &ECDSA {
@@ -241,11 +251,13 @@ impl VerificationAlgorithmImpl for EdDSA {
241251

242252
/// RSA PKCS#1 1.5 signatures.
243253
#[allow(non_camel_case_types)]
254+
#[cfg(not(feature = "no_heap"))]
244255
struct RSA_PKCS1 {
245256
digest_alg: &'static digest::Algorithm,
246257
min_bits: usize,
247258
}
248259

260+
#[cfg(not(feature = "no_heap"))]
249261
impl VerificationAlgorithmImpl for RSA_PKCS1 {
250262
fn verify(&self, public_key: Input, msg: Input, signature: Input)
251263
-> Result<(), ()> {
@@ -266,12 +278,15 @@ impl VerificationAlgorithmImpl for RSA_PKCS1 {
266278
macro_rules! rsa_pkcs1 {
267279
( $VERIFY_ALGORITHM:ident, $min_bits:expr, $min_bits_str:expr,
268280
$digest_alg_name:expr, $digest_alg:expr ) => {
281+
#[cfg(not(feature = "no_heap"))]
269282
#[doc="RSA PKCS#1 1.5 signatures of "]
270283
#[doc=$min_bits_str]
271284
#[doc="-8192 bits "]
272285
#[doc="using the "]
273286
#[doc=$digest_alg_name]
274287
#[doc=" digest algorithm."]
288+
///
289+
/// Not available in `no_heap` mode.
275290
pub static $VERIFY_ALGORITHM: VerificationAlgorithm =
276291
VerificationAlgorithm {
277292
implementation: &RSA_PKCS1 {
@@ -291,6 +306,7 @@ rsa_pkcs1!(RSA_PKCS1_3072_8192_SHA384, 3072, "3072", "SHA-384", &digest::SHA384)
291306

292307

293308
extern {
309+
#[cfg(not(feature = "no_heap"))]
294310
fn ECDSA_verify_signed_digest(group: *const ecc::EC_GROUP, hash_nid: c::int,
295311
digest: *const u8, digest_len: c::size_t,
296312
sig_der: *const u8, sig_der_len: c::size_t,
@@ -306,6 +322,7 @@ extern {
306322
signature: *const u8/*[64]*/,
307323
public_key: *const u8/*[32]*/) -> c::int;
308324

325+
#[cfg(not(feature = "no_heap"))]
309326
fn RSA_verify_pkcs1_signed_digest(min_bits: usize, max_bits: usize,
310327
digest_nid: c::int, digest: *const u8,
311328
digest_len: c::size_t, sig: *const u8,

0 commit comments

Comments
 (0)