Replace use_heap feature with alloc and std features; use alloc crate.

This commit is contained in:
Brian Smith 2019-07-04 08:06:13 -10:00
parent 7d36600ec8
commit 7071dda618
21 changed files with 94 additions and 79 deletions

View File

@ -67,13 +67,6 @@ e.g. export `CFLAGS=-D__ANDROID_API__=21`.
Additional Features that are Useful for Development
---------------------------------------------------
The `use_heap` feature enables functionality that uses the heap. This is on by
default. Disabling it is useful for code running in kernel space and some
embedded applications. For now some RSA, ECDH, and ECDSA signing functionality
still uses the heap. This feature will go away once RSA signing is the only
feature that uses the heap.
The `internal_benches` feature enable benchmarks of internal functions. These
benchmarks are only useful for people hacking on the implementation of *ring*.
(The benchmarks for the *ring* API are in the

View File

@ -325,12 +325,13 @@ cc = { version = "1.0.37", default-features = false }
[features]
# These features are documented in the top-level module's documentation.
default = ["use_heap", "dev_urandom_fallback"]
dev_urandom_fallback = ["use_heap", "lazy_static"]
default = ["alloc", "dev_urandom_fallback", "std"]
alloc = []
dev_urandom_fallback = ["std", "lazy_static"]
internal_benches = []
slow_tests = []
std = ["alloc"]
test_logging = []
use_heap = []
# XXX: debug = false because of https://github.com/rust-lang/rust/issues/34122

View File

@ -15,7 +15,7 @@
#[macro_use]
pub mod constant;
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
pub mod bigint;
pub mod montgomery;

View File

@ -36,8 +36,6 @@
//! [Static checking of units in Servo]:
//! https://blog.mozilla.org/research/2014/06/23/static-checking-of-units-in-servo/
#![allow(box_pointers)]
use crate::{
arithmetic::montgomery::*,
bits, bssl, c, error,

View File

@ -31,7 +31,7 @@ impl BitLength {
Ok(Self::from_usize_bits(bits))
}
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
#[inline]
pub fn half_rounded_up(&self) -> Self {
let round_up = self.0 & 1;
@ -43,7 +43,7 @@ impl BitLength {
self.0
}
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
#[inline]
pub fn as_usize_bytes_rounded_up(&self) -> usize {
// Equivalent to (self.0 + 7) / 8, except with no potential for
@ -55,7 +55,7 @@ impl BitLength {
(self.0 / 8) + round_up
}
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
#[inline]
pub fn try_sub_1(self) -> Result<BitLength, error::Unspecified> {
let sum = self.0.checked_sub(1).ok_or(error::Unspecified)?;

View File

@ -182,7 +182,7 @@ impl Context {
/// # Examples:
///
/// ```
/// # #[cfg(feature = "use_heap")]
/// # #[cfg(feature = "alloc")]
/// # {
/// use ring::{digest, test};
/// let expected_hex = "09ca7e4eaa6e8ae9c7d261167129184883644d07dfba7cbfbc4c8a2e08360d5b";

View File

@ -289,7 +289,7 @@ pub static ECDSA_P384_SHA384_ASN1: EcdsaVerificationAlgorithm = EcdsaVerificatio
mod tests {
use super::*;
use crate::test;
use std::vec::Vec;
use alloc::vec::Vec;
#[test]
fn test_digest_based_test_vectors() {

View File

@ -441,7 +441,6 @@ mod tests {
use super::*;
use crate::test;
use alloc::{format, vec, vec::Vec};
use std::print;
use untrusted;
const ZERO_SCALAR: Scalar = Scalar {
@ -1116,12 +1115,11 @@ mod tests {
) {
for i in 0..ops.num_limbs {
if actual[i] != expected[i] {
let mut s = std::string::String::new();
let mut s = alloc::string::String::new();
for j in 0..ops.num_limbs {
let formatted = format!("{:016x}", actual[ops.num_limbs - j - 1]);
s.push_str(&formatted);
}
print!("\n");
panic!("Actual != Expected,\nActual = {}", s);
}
}

View File

@ -36,7 +36,7 @@ use untrusted;
/// enum Error {
/// CryptoError,
///
/// # #[cfg(feature = "use_heap")]
/// # #[cfg(feature = "alloc")]
/// IOError(std::io::Error),
/// // [...]
/// }
@ -88,7 +88,7 @@ impl core::fmt::Display for Unspecified {
}
}
#[cfg(feature = "use_heap")]
#[cfg(feature = "std")]
impl std::error::Error for Unspecified {
#[inline]
fn cause(&self) -> Option<&dyn std::error::Error> {
@ -168,12 +168,12 @@ impl KeyRejected {
KeyRejected("PublicKeyIsMissing")
}
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
pub(crate) fn too_small() -> Self {
KeyRejected("TooSmall")
}
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
pub(crate) fn too_large() -> Self {
KeyRejected("TooLarge")
}
@ -186,7 +186,7 @@ impl KeyRejected {
KeyRejected("WrongAlgorithm")
}
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
pub(crate) fn private_modulus_len_not_multiple_of_512_bits() -> Self {
KeyRejected("PrivateModulusLenNotMultipleOf512Bits")
}
@ -196,7 +196,7 @@ impl KeyRejected {
}
}
#[cfg(feature = "use_std")]
#[cfg(feature = "std")]
impl std::error::Error for KeyRejected {
fn cause(&self) -> Option<&dyn std::error::Error> {
None

View File

@ -17,10 +17,10 @@
#[doc(hidden)]
pub mod der;
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
mod writer;
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
pub(crate) mod der_writer;
pub(crate) mod positive;

View File

@ -22,6 +22,8 @@
//! <table>
//! <tr><th>Feature
//! <th>Description
//! <tr><td><code>alloc (default)</code>
//! <td>Enable features that require use of the heap, RSA in particular.
//! <tr><td><code>dev_urandom_fallback (default)</code>
//! <td>This is only applicable to Linux. On Linux, by default,
//! <code>ring::rand::SystemRandom</code> will fall back to reading
@ -30,8 +32,9 @@
//! <code>dev_urandom_fallback</code> feature is disabled, such
//! fallbacks will not occur. See the documentation for
//! <code>rand::SystemRandom</code> for more details.
//! <tr><td><code>use_heap (default)</code>
//! <td>Enable features that require use of the heap, RSA in particular.
//! <tr><td><code>std (default)</code>
//! <td>Enable features that use libstd, in particular `std::error::Error`
//! integration.
//! </table>
#![doc(html_root_url = "https://briansmith.org/rustdoc/")]
@ -62,16 +65,15 @@
#![no_std]
#![cfg_attr(feature = "internal_benches", allow(unstable_features), feature(test))]
#[cfg(any(test, feature = "use_heap"))]
#[cfg(any(test, feature = "alloc"))]
extern crate alloc;
#[cfg(any(test, feature = "use_heap"))]
#[cfg(any(test, feature = "std"))]
extern crate std;
#[macro_use]
mod debug;
#[cfg(any(test, feature = "use_heap"))]
#[macro_use]
pub mod test;
@ -106,7 +108,7 @@ pub mod pbkdf2;
pub mod pkcs8;
pub mod rand;
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
mod rsa;
pub mod signature;

View File

@ -21,10 +21,10 @@
use crate::{c, error};
use untrusted;
#[cfg(any(test, feature = "use_heap"))]
#[cfg(any(test, feature = "alloc"))]
use crate::bits;
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
use core::num::Wrapping;
// XXX: Not correct for x32 ABIs.
@ -77,7 +77,7 @@ pub fn limbs_less_than_limbs_vartime(a: &[Limb], b: &[Limb]) -> bool {
}
#[inline]
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
pub fn limbs_less_than_limb_constant_time(a: &[Limb], b: Limb) -> LimbMask {
unsafe { LIMBS_less_than_limb(a.as_ptr(), b, a.len()) }
}
@ -87,13 +87,13 @@ pub fn limbs_are_zero_constant_time(limbs: &[Limb]) -> LimbMask {
unsafe { LIMBS_are_zero(limbs.as_ptr(), limbs.len()) }
}
#[cfg(any(test, feature = "use_heap"))]
#[cfg(any(test, feature = "alloc"))]
#[inline]
pub fn limbs_are_even_constant_time(limbs: &[Limb]) -> LimbMask {
unsafe { LIMBS_are_even(limbs.as_ptr(), limbs.len()) }
}
#[cfg(any(test, feature = "use_heap"))]
#[cfg(any(test, feature = "alloc"))]
#[inline]
pub fn limbs_equal_limb_constant_time(a: &[Limb], b: Limb) -> LimbMask {
unsafe { LIMBS_equal_limb(a.as_ptr(), b, a.len()) }
@ -106,7 +106,7 @@ pub fn limbs_equal_limb_constant_time(a: &[Limb], b: Limb) -> LimbMask {
// with respect to `a.len()` or the value of the result or the value of the
// most significant bit (It's 1, unless the input is zero, in which case it's
// zero.)
#[cfg(any(test, feature = "use_heap"))]
#[cfg(any(test, feature = "alloc"))]
pub fn limbs_minimal_bits(a: &[Limb]) -> bits::BitLength {
for num_limbs in (1..=a.len()).rev() {
let high_limb = a[num_limbs - 1];
@ -252,7 +252,7 @@ pub fn big_endian_from_limbs(limbs: &[Limb], out: &mut [u8]) {
}
}
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
pub type Window = Limb;
/// Processes `limbs` as a sequence of 5-bit windows, folding the windows from
@ -267,7 +267,7 @@ pub type Window = Limb;
/// channels as long as `init` and `fold` are side-channel free.
///
/// Panics if `limbs` is empty.
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
pub fn fold_5_bit_windows<R, I: FnOnce(Window) -> R, F: Fn(R, Window) -> R>(
limbs: &[Limb],
init: I,
@ -333,16 +333,16 @@ pub fn fold_5_bit_windows<R, I: FnOnce(Window) -> R, F: Fn(R, Window) -> R>(
}
extern "C" {
#[cfg(any(test, feature = "use_heap"))]
#[cfg(any(test, feature = "alloc"))]
fn LIMB_shr(a: Limb, shift: c::size_t) -> Limb;
#[cfg(any(test, feature = "use_heap"))]
#[cfg(any(test, feature = "alloc"))]
fn LIMBS_are_even(a: *const Limb, num_limbs: c::size_t) -> LimbMask;
fn LIMBS_are_zero(a: *const Limb, num_limbs: c::size_t) -> LimbMask;
#[cfg(any(test, feature = "use_heap"))]
#[cfg(any(test, feature = "alloc"))]
fn LIMBS_equal_limb(a: *const Limb, b: Limb, num_limbs: c::size_t) -> LimbMask;
fn LIMBS_less_than(a: *const Limb, b: *const Limb, num_limbs: c::size_t) -> LimbMask;
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
fn LIMBS_less_than_limb(a: *const Limb, b: Limb, num_limbs: c::size_t) -> LimbMask;
fn LIMBS_reduce_once(r: *mut Limb, m: *const Limb, num_limbs: c::size_t);
}
@ -453,7 +453,7 @@ mod tests {
}
#[test]
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
fn test_limbs_less_than_limb_constant_time() {
static LESSER: &[(&[Limb], Limb)] = &[
(&[0], 1),

View File

@ -16,7 +16,7 @@ use super::PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN;
use crate::{bits, digest, error, io::der};
use untrusted;
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
use crate::rand;
/// Common features of both RSA padding encoding and RSA padding verification.
@ -29,7 +29,7 @@ pub trait Padding: 'static + Sync + crate::sealed::Sealed + core::fmt::Debug {
/// An RSA signature encoding as described in [RFC 3447 Section 8].
///
/// [RFC 3447 Section 8]: https://tools.ietf.org/html/rfc3447#section-8
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
pub trait RsaEncoding: Padding {
#[doc(hidden)]
fn encode(
@ -74,7 +74,7 @@ impl Padding for PKCS1 {
}
}
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
impl RsaEncoding for PKCS1 {
fn encode(
&self,
@ -398,7 +398,7 @@ impl Verification for PSS {
}
struct PSSMetrics {
#[cfg_attr(not(feature = "use_heap"), allow(dead_code))]
#[cfg_attr(not(feature = "alloc"), allow(dead_code))]
em_len: usize,
db_len: usize,
ps_len: usize,
@ -562,7 +562,7 @@ mod test {
}
// Tests PSS encoding for various public modulus lengths.
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
#[test]
fn test_pss_padding_encode() {
test::run(

View File

@ -610,7 +610,7 @@ mod tests {
// We intentionally avoid `use super::*` so that we are sure to use only
// the public API; this ensures that enough of the API is public.
use crate::{rand, signature};
use std::vec;
use alloc::vec;
// `KeyPair::sign` requires that the output buffer is the same length as
// the public key modulus. Test what happens when it isn't the same length.

View File

@ -107,7 +107,7 @@ macro_rules! rsa_params {
$doc_str:expr ) => {
#[doc=$doc_str]
///
/// Only available in `use_heap` mode.
/// Only available in `alloc` mode.
pub static $VERIFY_ALGORITHM: RsaParameters = RsaParameters {
padding_alg: $PADDING_ALGORITHM,
min_bits: bits::BitLength::from_usize_bits($min_bits),

View File

@ -195,7 +195,7 @@
//! ```
//! use ring::{rand, signature};
//!
//! # #[cfg(feature = "use_heap")]
//! # #[cfg(feature = "std")]
//! fn sign_and_verify_rsa(private_key_path: &std::path::Path,
//! public_key_path: &std::path::Path)
//! -> Result<(), MyError> {
@ -223,14 +223,14 @@
//!
//! #[derive(Debug)]
//! enum MyError {
//! # #[cfg(feature = "use_heap")]
//! # #[cfg(feature = "std")]
//! IO(std::io::Error),
//! BadPrivateKey,
//! OOM,
//! BadSignature,
//! }
//!
//! # #[cfg(feature = "use_heap")]
//! # #[cfg(feature = "std")]
//! fn read_file(path: &std::path::Path) -> Result<Vec<u8>, MyError> {
//! use std::io::Read;
//!
@ -240,7 +240,7 @@
//! Ok(contents)
//! }
//! #
//! # #[cfg(not(feature = "use_heap"))]
//! # #[cfg(not(feature = "std"))]
//! # fn sign_and_verify_rsa(_private_key_path: &std::path::Path,
//! # _public_key_path: &std::path::Path)
//! # -> Result<(), ()> {
@ -279,7 +279,7 @@ pub use crate::ec::{
},
};
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
pub use crate::rsa::{
signing::RsaKeyPair,
signing::RsaSubjectPublicKey,

View File

@ -117,12 +117,13 @@
//! stack trace to the line in the test code that panicked: entry 9 in the
//! stack trace pointing to line 652 of the file `example.rs`.
#[cfg(feature = "use_heap")]
use crate::bits;
use crate::{digest, error};
#[cfg(feature = "alloc")]
use alloc::{format, string::String, vec::Vec};
#[cfg(feature = "std")]
use crate::{bits, digest, error};
#[cfg(feature = "std")]
use std::println;
/// `compile_time_assert_clone::<T>();` fails to compile if `T` doesn't
@ -145,14 +146,23 @@ pub fn compile_time_assert_sync<T: Sync>() {}
/// implement `Debug`.
pub fn compile_time_assert_debug<T: core::fmt::Debug>() {}
/// `compile_time_assert_debug::<T>();` fails to compile if `T` doesn't
/// implement `std::error::Error`.
#[cfg(feature = "std")]
pub fn compile_time_assert_std_error_error<T: std::error::Error>() {}
/// A test case. A test case consists of a set of named attributes. Every
/// attribute in the test case must be consumed exactly once; this helps catch
/// typos and omissions.
///
/// Requires the `std` default feature to be enabled.
#[cfg(feature = "std")]
#[derive(Debug)]
pub struct TestCase {
attributes: Vec<(String, String, bool)>,
}
#[cfg(feature = "std")]
impl TestCase {
/// Maps the string "true" to true and the string "false" to false.
pub fn consume_bool(&mut self, key: &str) -> bool {
@ -247,7 +257,7 @@ impl TestCase {
/// Returns the value of an attribute that is an integer, in decimal
/// notation, as a bit length.
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
pub fn consume_usize_bits(&mut self, key: &str) -> bits::BitLength {
let s = self.consume_string(key);
let bits = s.parse::<usize>().unwrap();
@ -300,6 +310,9 @@ pub struct File<'a> {
/// Parses test cases out of the given file, calling `f` on each vector until
/// `f` fails or until all the test vectors have been read. `f` can indicate
/// failure either by returning `Err()` or by panicking.
///
/// Requires the `std` default feature to be enabled
#[cfg(feature = "std")]
pub fn run<F>(test_file: File, mut f: F)
where
F: FnMut(&str, &mut TestCase) -> Result<(), error::Unspecified>,
@ -309,7 +322,6 @@ where
let mut current_section = String::from("");
let mut failed = false;
#[allow(box_pointers)]
while let Some(mut test_case) = parse_test_case(&mut current_section, lines) {
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
f(&current_section, &mut test_case)
@ -349,6 +361,7 @@ where
/// Decode an string of hex digits into a sequence of bytes. The input must
/// have an even number of digits.
#[cfg(feature = "alloc")]
pub fn from_hex(hex_str: &str) -> Result<Vec<u8>, String> {
if hex_str.len() % 2 != 0 {
return Err(String::from(
@ -365,6 +378,7 @@ pub fn from_hex(hex_str: &str) -> Result<Vec<u8>, String> {
Ok(result)
}
#[cfg(feature = "alloc")]
fn from_hex_digit(d: u8) -> Result<u8, String> {
if d >= b'0' && d <= b'9' {
Ok(d - b'0')
@ -377,6 +391,8 @@ fn from_hex_digit(d: u8) -> Result<u8, String> {
}
}
#[cfg(feature = "std")]
fn parse_test_case(
current_section: &mut String,
lines: &mut dyn Iterator<Item = &str>,
@ -453,7 +469,7 @@ fn parse_test_case(
/// of randomized algorithms & protocols using known-answer-tests where the
/// test vectors contain the random seed to use. They are also especially
/// useful for some types of fuzzing.
#[allow(missing_docs)]
#[doc(hidden)]
pub mod rand {
use crate::{error, polyfill, rand};

View File

@ -97,7 +97,7 @@ fn test_agreement_ecdh_x25519_rfc_iterated() {
fn expect_iterated_x25519(
expected_result: &str,
range: std::ops::Range<usize>,
range: core::ops::Range<usize>,
k: &mut Vec<u8>,
u: &mut Vec<u8>,
) {

View File

@ -39,7 +39,7 @@ use ring::{
// ECDSA *signing* tests are in src/ec/ecdsa/signing.rs.
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
#[test]
fn ecdsa_from_pkcs8_test() {
test::run(
@ -123,7 +123,7 @@ fn ecdsa_generate_pkcs8_test() {
println!();
println!();
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
let _ = signature::EcdsaKeyPair::from_pkcs8(*alg, pkcs8.as_ref()).unwrap();
}
}

7
tests/error_tests.rs Normal file
View File

@ -0,0 +1,7 @@
#[cfg(feature = "std")]
#[test]
fn error_impl_std_error_error_test() {
use ring::{error, test};
test::compile_time_assert_std_error_error::<error::Unspecified>();
test::compile_time_assert_std_error_error::<error::KeyRejected>();
}

View File

@ -31,7 +31,7 @@
warnings
)]
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
use ring::{
error,
io::der,
@ -40,7 +40,7 @@ use ring::{
test, test_file,
};
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
#[test]
fn rsa_from_pkcs8_test() {
test::run(
@ -63,7 +63,7 @@ fn rsa_from_pkcs8_test() {
);
}
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
#[test]
fn test_signature_rsa_pkcs1_sign() {
let rng = rand::SystemRandom::new();
@ -104,7 +104,7 @@ fn test_signature_rsa_pkcs1_sign() {
);
}
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
#[test]
fn test_signature_rsa_pss_sign() {
test::run(
@ -141,7 +141,7 @@ fn test_signature_rsa_pss_sign() {
);
}
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
#[test]
fn test_signature_rsa_pkcs1_verify() {
test::run(
@ -199,7 +199,7 @@ fn test_signature_rsa_pkcs1_verify() {
);
}
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
#[test]
fn test_signature_rsa_pss_verify() {
test::run(
@ -257,7 +257,7 @@ fn test_signature_rsa_pss_verify() {
// Test for `primitive::verify()`. Read public key parts from a file
// and use them to verify a signature.
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
#[test]
fn test_signature_rsa_primitive_verification() {
test::run(
@ -277,7 +277,7 @@ fn test_signature_rsa_primitive_verification() {
)
}
#[cfg(feature = "use_heap")]
#[cfg(feature = "alloc")]
#[test]
fn rsa_test_public_key_coverage() {
const PRIVATE_KEY: &[u8] = include_bytes!("rsa_test_private_key_2048.p8");