diff --git a/.travis.yml b/.travis.yml
index 56a738fc00..4346001c9a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -416,6 +416,38 @@ matrix:
sources:
- ubuntu-toolchain-r-test
+ - env: TARGET_X=x86_64-fortanix-unknown-sgx FEATURES_X= MODE_X=DEBUG KCOV=0
+ rust: nightly
+ os: linux
+ dist: trusty
+
+ - env: TARGET_X=x86_64-fortanix-unknown-sgx FEATURES_X= MODE_X=RELWITHDEBINFO KCOV=0
+ rust: nightly
+ os: linux
+ dist: trusty
+
+ - env: TARGET_X=x86_64-fortanix-unknown-sgx CC_X=gcc-7 FEATURES_X= MODE_X=DEBUG KCOV=0
+ rust: nightly
+ os: linux
+ dist: trusty
+ addons:
+ apt:
+ packages:
+ - gcc-7
+ sources:
+ - ubuntu-toolchain-r-test
+
+ - env: TARGET_X=x86_64-fortanix-unknown-sgx CC_X=gcc-7 FEATURES_X= MODE_X=RELWITHDEBINFO KCOV=0
+ rust: nightly
+ os: linux
+ dist: trusty
+ addons:
+ apt:
+ packages:
+ - gcc-7
+ sources:
+ - ubuntu-toolchain-r-test
+
- env: TARGET_X=x86_64-apple-darwin FEATURES_X= MODE_X=DEBUG KCOV=0
rust: beta
os: osx
diff --git a/Cargo.toml b/Cargo.toml
index 4a66b38f77..6e905cbaa9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -83,6 +83,7 @@ include = [
"crypto/fipsmodule/modes/asm/ghashv8-armx.pl",
"crypto/fipsmodule/modes/gcm.c",
"crypto/fipsmodule/modes/internal.h",
+ "crypto/fipsmodule/rand/asm/rdrand-x86_64.pl",
"crypto/fipsmodule/sha/asm/sha256-586.pl",
"crypto/fipsmodule/sha/asm/sha256-armv4.pl",
"crypto/fipsmodule/sha/asm/sha512-586.pl",
@@ -324,6 +325,7 @@ internal_benches = []
slow_tests = []
test_logging = []
use_heap = []
+force_std_detection = []
# XXX: debug = false because of https://github.com/rust-lang/rust/issues/34122
diff --git a/build.rs b/build.rs
index 45cfab7ec7..3cafc7fc6a 100644
--- a/build.rs
+++ b/build.rs
@@ -91,6 +91,7 @@ const RING_SRCS: &[(&[&str], &str)] = &[
(&[X86_64], "crypto/fipsmodule/modes/asm/ghash-x86_64.pl"),
(&[X86_64], "crypto/poly1305/asm/poly1305-x86_64.pl"),
(&[X86_64], SHA512_X86_64),
+ (&[X86_64], "crypto/fipsmodule/rand/asm/rdrand-x86_64.pl"),
(&[AARCH64, ARM], "crypto/fipsmodule/aes/asm/aesv8-armx.pl"),
(&[AARCH64, ARM], "crypto/fipsmodule/modes/asm/ghashv8-armx.pl"),
diff --git a/crypto/fipsmodule/rand/asm/rdrand-x86_64.pl b/crypto/fipsmodule/rand/asm/rdrand-x86_64.pl
new file mode 100644
index 0000000000..056dd74878
--- /dev/null
+++ b/crypto/fipsmodule/rand/asm/rdrand-x86_64.pl
@@ -0,0 +1,79 @@
+#!/usr/bin/env perl
+
+# Copyright (c) 2015, Google Inc.
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+$flavour = shift;
+$output = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}../../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+die "can't locate x86_64-xlate.pl";
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+print<<___;
+.text
+
+# CRYPTO_rdrand writes eight bytes of random data from the hardware RNG to
+# |out|. It returns one on success or zero on hardware failure.
+# int CRYPTO_rdrand(uint8_t out[8]);
+.globl CRYPTO_rdrand
+.type CRYPTO_rdrand,\@function,1
+.align 16
+CRYPTO_rdrand:
+.cfi_startproc
+ xorq %rax, %rax
+ # This is rdrand %rcx. It sets rcx to a random value and sets the carry
+ # flag on success.
+ .byte 0x48, 0x0f, 0xc7, 0xf1
+ # An add-with-carry of zero effectively sets %rax to the carry flag.
+ adcq %rax, %rax
+ movq %rcx, 0(%rdi)
+ retq
+.cfi_endproc
+
+# CRYPTO_rdrand_multiple8_buf fills |len| bytes at |buf| with random data from
+# the hardware RNG. The |len| argument must be a multiple of eight. It returns
+# one on success and zero on hardware failure.
+# int CRYPTO_rdrand_multiple8_buf(uint8_t *buf, size_t len);
+.globl CRYPTO_rdrand_multiple8_buf
+.type CRYPTO_rdrand_multiple8_buf,\@function,2
+.align 16
+CRYPTO_rdrand_multiple8_buf:
+.cfi_startproc
+ test %rsi, %rsi
+ jz .Lout
+ movq \$8, %rdx
+.Lloop:
+ # This is rdrand %rcx. It sets rcx to a random value and sets the carry
+ # flag on success.
+ .byte 0x48, 0x0f, 0xc7, 0xf1
+ jnc .Lerr
+ movq %rcx, 0(%rdi)
+ addq %rdx, %rdi
+ subq %rdx, %rsi
+ jnz .Lloop
+.Lout:
+ movq \$1, %rax
+ retq
+.Lerr:
+ xorq %rax, %rax
+ retq
+.cfi_endproc
+___
+
+close STDOUT; # flush
diff --git a/mk/travis.sh b/mk/travis.sh
index 20545eb387..639f03ad75 100755
--- a/mk/travis.sh
+++ b/mk/travis.sh
@@ -47,7 +47,7 @@ if [[ "$TARGET_X" =~ ^(arm|aarch64) && ! "$TARGET_X" =~ android ]]; then
sudo apt-get install --no-install-recommends binfmt-support qemu-user-binfmt -y
fi
-if [[ ! "$TARGET_X" =~ "x86_64-" ]]; then
+if [[ "$TARGET_X" != "$(rustc --version --verbose|sed -n 's/^host: //p')" ]]; then
rustup target add "$TARGET_X"
# By default cargo/rustc seems to use cc for linking, We installed the
@@ -122,6 +122,10 @@ armv7-linux-androideabi)
adb emu kill
+ ;;
+x86_64-fortanix-unknown-sgx)
+ # Can't run SGX in Travis. Only build, but don't run, the tests
+ RUSTFLAGS="-C target-feature=+aes,+pclmul" cargo test -vv -j2 --no-run ${mode-} ${FEATURES_X-} --target=$TARGET_X
;;
*)
cargo test -vv -j2 ${mode-} ${FEATURES_X-} --target=$TARGET_X
diff --git a/mk/update-travis-yml.py b/mk/update-travis-yml.py
index 88b4177e1d..1222d68fd3 100755
--- a/mk/update-travis-yml.py
+++ b/mk/update-travis-yml.py
@@ -47,6 +47,7 @@
"arm-unknown-linux-gnueabihf" : [ "arm-linux-gnueabihf-gcc" ],
"i686-unknown-linux-gnu" : linux_compilers,
"x86_64-unknown-linux-gnu" : linux_compilers,
+ "x86_64-fortanix-unknown-sgx" : linux_compilers,
"x86_64-apple-darwin" : osx_compilers,
}
@@ -76,17 +77,20 @@
"aarch64-unknown-linux-gnu",
"i686-unknown-linux-gnu",
"arm-unknown-linux-gnueabihf",
+ "x86_64-fortanix-unknown-sgx",
],
}
def format_entries():
- return "\n".join([format_entry(os, target, compiler, rust, mode, features)
- for rust in rusts
- for os in oss
- for target in targets[os]
- for compiler in compilers[target]
- for mode in modes
- for features in feature_sets])
+ return "\n".join([entry for entry in
+ (format_entry(os, target, compiler, rust, mode, features)
+ for rust in rusts
+ for os in oss
+ for target in targets[os]
+ for compiler in compilers[target]
+ for mode in modes
+ for features in feature_sets)
+ if entry is not None])
# We use alternative names (the "_X" suffix) so that, in mk/travis.sh, we can
# ensure that we set the specific variables we want and that no relevant
@@ -111,6 +115,12 @@ def format_entries():
%(sources)s"""
def format_entry(os, target, compiler, rust, mode, features):
+ if target == "x86_64-fortanix-unknown-sgx" and rust != "nightly":
+ return
+ # Tracked in https://github.com/fortanix/rust-sgx/issues/64
+ if target == "x86_64-fortanix-unknown-sgx" and compiler == "clang":
+ return
+
target_words = target.split("-")
arch = target_words[0]
vendor = target_words[1]
@@ -127,13 +137,11 @@ def format_entry(os, target, compiler, rust, mode, features):
mode == "DEBUG")
if sys == "darwin":
- abi = sys
sys = "macos"
elif sys == "androideabi":
- abi = sys
sys = "linux"
- else:
- abi = target_words[3]
+ elif target == "x86_64-fortanix-unknown-sgx":
+ sys = "linux"
def prefix_all(prefix, xs):
return [prefix + x for x in xs]
@@ -263,7 +271,7 @@ def main():
file.seek(0)
file.write(new_contents)
file.truncate()
- print new_contents
+ print new_contents,
if __name__ == '__main__':
main()
diff --git a/src/aead/aes.rs b/src/aead/aes.rs
index 5bd20eb7d3..203e99a139 100644
--- a/src/aead/aes.rs
+++ b/src/aead/aes.rs
@@ -74,6 +74,7 @@ impl Key {
})?;
},
+ #[cfg(not(target_env = "sgx"))]
_ => {
extern "C" {
fn GFp_aes_nohw_set_encrypt_key(
@@ -121,6 +122,7 @@ impl Key {
}
},
+ #[cfg(not(target_env = "sgx"))]
_ => {
extern "C" {
fn GFp_aes_nohw_encrypt(a: *const Block, r: *mut Block, key: &AES_KEY);
@@ -246,6 +248,7 @@ pub enum Implementation {
#[cfg(target_arch = "arm")]
BSAES = 3,
+ #[cfg(not(target_env = "sgx"))]
Fallback = 4,
}
@@ -268,7 +271,15 @@ fn detect_implementation(cpu_features: cpu::Features) -> Implementation {
}
}
- Implementation::Fallback
+ #[cfg(not(target_env = "sgx"))]
+ {
+ Implementation::Fallback
+ }
+
+ #[cfg(target_env = "sgx")]
+ {
+ panic!("No AES implementation available!")
+ }
}
#[must_use]
diff --git a/src/aead/gcm.rs b/src/aead/gcm.rs
index 46522c2905..4a350aedc3 100644
--- a/src/aead/gcm.rs
+++ b/src/aead/gcm.rs
@@ -57,6 +57,7 @@ impl Key {
}
},
+ #[cfg(not(target_env = "sgx"))]
Implementation::Fallback => {
extern "C" {
fn GFp_gcm_init_4bit(key: &mut Key, h: &[u64; 2]);
@@ -139,6 +140,7 @@ impl Context {
}
},
+ #[cfg(not(target_env = "sgx"))]
Implementation::Fallback => {
extern "C" {
fn GFp_gcm_ghash_4bit(
@@ -177,6 +179,7 @@ impl Context {
}
},
+ #[cfg(not(target_env = "sgx"))]
Implementation::Fallback => {
extern "C" {
fn GFp_gcm_gmult_4bit(ctx: &mut Context, Htable: *const GCM128_KEY);
@@ -199,6 +202,7 @@ impl Context {
pub(super) fn is_avx2(&self, cpu_features: cpu::Features) -> bool {
match detect_implementation(cpu_features) {
Implementation::CLMUL => has_avx_movbe(self.cpu_features),
+ #[cfg(not(target_env = "sgx"))]
_ => false,
}
}
@@ -234,6 +238,7 @@ enum Implementation {
#[cfg(target_arch = "arm")]
NEON,
+ #[cfg(not(target_env = "sgx"))]
Fallback,
}
@@ -252,7 +257,15 @@ fn detect_implementation(cpu: cpu::Features) -> Implementation {
}
}
- Implementation::Fallback
+ #[cfg(not(target_env = "sgx"))]
+ {
+ Implementation::Fallback
+ }
+
+ #[cfg(target_env = "sgx")]
+ {
+ panic!("No GCM implementation available!")
+ }
}
#[cfg(target_arch = "x86_64")]
diff --git a/src/cpu.rs b/src/cpu.rs
index 7b1b299401..0794f315f7 100644
--- a/src/cpu.rs
+++ b/src/cpu.rs
@@ -32,11 +32,145 @@ pub(crate) fn features() -> Features {
let () = INIT.call_once(|| {
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
{
- extern "C" {
- fn GFp_cpuid_setup();
+ #[cfg(any(feature = "force_std_detection", all(target_env = "sgx" /*, target_vendor = "fortanix"*/)))]
+ {
+ extern "C" {
+ static mut GFp_ia32cap_P: [u32; 4];
+ }
+ let [l1edx, l1ecx, l7ebx, l7ecx] = unsafe { &mut GFp_ia32cap_P };
+
+ if is_x86_feature_detected!("aes") {
+ *l1ecx |= 1<<25;
+ }
+ if is_x86_feature_detected!("pclmulqdq") {
+ *l1ecx |= 1<<1;
+ }
+ if is_x86_feature_detected!("rdrand") {
+ *l1ecx |= 1<<30;
+ }
+ if is_x86_feature_detected!("rdseed") {
+ *l7ebx |= 1<<18;
+ }
+ if is_x86_feature_detected!("tsc") {
+ *l1edx |= 1<<4;
+ }
+ if is_x86_feature_detected!("mmx") {
+ *l1edx |= 1<<23;
+ }
+ if is_x86_feature_detected!("sse") {
+ *l1edx |= 1<<25;
+ }
+ if is_x86_feature_detected!("sse2") {
+ *l1edx |= 1<<26;
+ }
+ if is_x86_feature_detected!("sse3") {
+ *l1ecx |= 1<<0;
+ }
+ if is_x86_feature_detected!("ssse3") {
+ *l1ecx |= 1<<9;
+ }
+ if is_x86_feature_detected!("sse4.1") {
+ *l1ecx |= 1<<19;
+ }
+ if is_x86_feature_detected!("sse4.2") {
+ *l1ecx |= 1<<20;
+ }
+ if is_x86_feature_detected!("sha") {
+ *l7ebx |= 1<<29;
+ }
+ if is_x86_feature_detected!("avx") {
+ *l1ecx |= 1<<28;
+ }
+ if is_x86_feature_detected!("avx2") {
+ *l7ebx |= 1<<5;
+ }
+ if is_x86_feature_detected!("avx512f") {
+ *l7ebx |= 1<<16;
+ }
+ if is_x86_feature_detected!("avx512cd") {
+ *l7ebx |= 1<<28;
+ }
+ if is_x86_feature_detected!("avx512er") {
+ *l7ebx |= 1<<27;
+ }
+ if is_x86_feature_detected!("avx512pf") {
+ *l7ebx |= 1<<26;
+ }
+ if is_x86_feature_detected!("avx512bw") {
+ *l7ebx |= 1<<30;
+ }
+ if is_x86_feature_detected!("avx512dq") {
+ *l7ebx |= 1<<17;
+ }
+ if is_x86_feature_detected!("avx512vl") {
+ *l7ebx |= 1<<31;
+ }
+ if is_x86_feature_detected!("avx512ifma") {
+ *l7ebx |= 1<<21;
+ }
+ if is_x86_feature_detected!("avx512vbmi") {
+ *l7ecx |= 1<<1;
+ }
+ if is_x86_feature_detected!("avx512vpopcntdq") {
+ *l7ecx |= 1<<14;
+ }
+ if is_x86_feature_detected!("fma") {
+ *l1ecx |= 1<<12;
+ }
+ if is_x86_feature_detected!("bmi1") {
+ *l7ebx |= 1<<3;
+ }
+ if is_x86_feature_detected!("bmi2") {
+ *l7ebx |= 1<<8;
+ }
+ if is_x86_feature_detected!("popcnt") {
+ *l1ecx |= 1<<23;
+ }
+ if is_x86_feature_detected!("fxsr") {
+ *l1edx |= 1<<24;
+ }
+ if is_x86_feature_detected!("xsave") {
+ *l1ecx |= 1<<26;
+ }
+ /* will be stable on 1.33.0
+ if is_x86_feature_detected!("cmpxchg16b") {
+ *l1ecx |= 1<<13;
+ }
+ if is_x86_feature_detected!("adx") {
+ *l7ebx |= 1<<19;
+ }
+ */
+
+ // Rust can't detect the MOVBE feature yet, but it's widely
+ // available.
+ *l1ecx |= 1<<22;
+
+ // This bit is reserved in the CPUID specification, but the
+ // BoringSSL detection code uses it to represent that this
+ // is an Intel CPU. However, this bit is only used in
+ // conjunction with the AVX bit to test for presence of
+ // AVX, thus serving no purpose. Always set it.
+ *l1edx |= 1<<30;
+
+ // Features that don't map to leaf 1 or leaf 7:
+ // Leaf 0xd:
+ // * xsaveopt
+ // * xsaves
+ // * xsavec
+ // Leaf 0x8000_0001:
+ // * sse4a
+ // * abm
+ // * lzcnt
+ // * tbm
}
- unsafe {
- GFp_cpuid_setup();
+ #[cfg(not(any(feature = "force_std_detection", all(target_env = "sgx" /*, target_vendor = "fortanix"*/))))]
+ {
+ extern "C" {
+ fn GFp_cpuid_setup();
+ }
+ unsafe {
+ GFp_cpuid_setup();
+ }
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 62e956bba3..e2d6155ccd 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -30,6 +30,12 @@
//! dev_urandom_fallback feature is disabled, such
//! fallbacks will not occur. See the documentation for
//! rand::SystemRandom for more details.
+//!
force_std_detection
+//! std::is_x86_feature_detected macro will be used
+//! instead.
//! use_heap (default)
//!