diff --git a/.devcontainer.json b/.devcontainer.json index 6e40bb7f275..a6b6339612e 100644 --- a/.devcontainer.json +++ b/.devcontainer.json @@ -4,7 +4,7 @@ // - https://code.visualstudio.com/docs/remote/devcontainerjson-reference { // Do not modify manually. This value is automatically updated by ./scripts/docker_build . - "image": "sha256:1efea0378c65660a81d23f82740f666da3f57108d8cb63d1217fcf67d908093c", + "image": "sha256:ab889141f07b886f02ca3ec664341d7dfada94826c5538842b795b005bc1a417", "extensions": [ "bazelbuild.vscode-bazel", "bodil.prettier-toml", diff --git a/Dockerfile b/Dockerfile index c213f053288..62dbe9881f7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -52,6 +52,26 @@ RUN apt-get --yes update \ && git --version \ && shellcheck --version +# We build our own fork of ring crate from its source. This requires some extra +# build config that isn't needed for the version published on crates.io, which +# includes pre-generated assets. +# Ring requires nasm, and a specific version of clang & llvm +ARG llvm_version=14 +RUN echo "deb http://apt.llvm.org/buster/ llvm-toolchain-buster-$llvm_version main" >> /etc/apt/sources.list.d/llvm.list \ + && curl https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - \ + && apt-get update --yes \ + && apt-get install --no-install-recommends --yes \ + clang-${llvm_version} \ + llvm-${llvm_version} \ + nasm \ + && rm --recursive --force /var/lib/apt/lists/* + +# Ring epects these ENV variables in its build tooling +ENV llvm_version=$llvm_version +ENV CC_x86_64_unknown_uefi=clang-$llvm_version +ENV AR_x86_64_unknown_uefi=llvm-ar-$llvm_version +ENV NASM_EXECUTABLE=nasm + # Install a version of docker CLI. RUN curl --fail --silent --show-error --location https://download.docker.com/linux/debian/gpg | apt-key add - RUN echo "deb [arch=amd64] https://download.docker.com/linux/debian buster stable" > /etc/apt/sources.list.d/backports.list \ diff --git a/experimental/uefi/app/Cargo.lock b/experimental/uefi/app/Cargo.lock index 4492239ac66..6345fbbc9ef 100644 --- a/experimental/uefi/app/Cargo.lock +++ b/experimental/uefi/app/Cargo.lock @@ -2,6 +2,18 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "anyhow" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + [[package]] name = "bit_field" version = "0.10.1" @@ -14,12 +26,106 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bytes" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" + +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cmake" +version = "0.1.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8ad8cef104ac57b68b89df3208164d228503abbdce70f6880ffa3d970e7443a" +dependencies = [ + "cc", +] + +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + +[[package]] +name = "fastrand" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +dependencies = [ + "instant", +] + +[[package]] +name = "fixedbitset" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "279fb028e20b3c4c320317955b77c5e0c9701f05a1d309905d6fc702cdc5053e" + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" + +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + +[[package]] +name = "indexmap" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "itertools" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +dependencies = [ + "either", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f" + [[package]] name = "log" version = "0.4.16" @@ -29,6 +135,40 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "multimap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" + +[[package]] +name = "oak_remote_attestation" +version = "0.1.0" +dependencies = [ + "anyhow", + "bytes", + "log", + "prost", + "prost-build", + "ring", +] + +[[package]] +name = "once_cell" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" + +[[package]] +name = "petgraph" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a13a2fa9d0b63e5f22328828741e523766fff0ee9e779316902290dff3f824f" +dependencies = [ + "fixedbitset", + "indexmap", +] + [[package]] name = "proc-macro2" version = "1.0.36" @@ -38,6 +178,61 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "prost" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bd5316aa8f5c82add416dfbc25116b84b748a21153f512917e8143640a71bbd" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "328f9f29b82409216decb172d81e936415d21245befa79cd34c3f29d87d1c50b" +dependencies = [ + "bytes", + "cfg-if", + "cmake", + "heck", + "itertools", + "lazy_static", + "log", + "multimap", + "petgraph", + "prost", + "prost-types", + "regex", + "tempfile", + "which", +] + +[[package]] +name = "prost-derive" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df35198f0777b75e9ff669737c6da5136b59dba33cf5a010a6d1cc4d56defc6f" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-types" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "926681c118ae6e512a3ccefd4abbe5521a14f4cc1e207356d4d00c0b7f2006fd" +dependencies = [ + "bytes", + "prost", +] + [[package]] name = "qemu-exit" version = "3.0.1" @@ -53,6 +248,57 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "redox_syscall" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "ring" +version = "0.17.0-not-released-yet" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "winapi", +] + +[[package]] +name = "spin" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "511254be0c5bcf062b019a6c89c01a664aa359ded62f78aa72c6fc137c0590e5" + [[package]] name = "syn" version = "1.0.89" @@ -64,6 +310,20 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] + [[package]] name = "ucs2" version = "0.3.2" @@ -113,6 +373,7 @@ name = "uefi-simple" version = "0.1.0" dependencies = [ "log", + "oak_remote_attestation", "uefi", "uefi-services", ] @@ -122,3 +383,42 @@ name = "unicode-xid" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "which" +version = "4.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae" +dependencies = [ + "either", + "lazy_static", + "libc", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/experimental/uefi/app/Cargo.toml b/experimental/uefi/app/Cargo.toml index 5dd8aaf52d5..4e47574c818 100644 --- a/experimental/uefi/app/Cargo.toml +++ b/experimental/uefi/app/Cargo.toml @@ -9,6 +9,7 @@ license = "Apache-2.0" uefi = { version = "*", features = ["exts"] } uefi-services = "*" log = { version = "*" } +oak_remote_attestation = { path = "../../../remote_attestation/rust" } [dev-dependencies] uefi-services = { version = "*", features = ["qemu"] } diff --git a/scripts/common b/scripts/common index e6ede5200c5..a9da2eb23af 100644 --- a/scripts/common +++ b/scripts/common @@ -20,10 +20,10 @@ readonly DOCKER_IMAGE_NAME='gcr.io/oak-ci/oak:latest' # from a registry first. # Do not modify manually. This value is automatically updated by ./scripts/docker_build . -readonly DOCKER_IMAGE_ID='sha256:1efea0378c65660a81d23f82740f666da3f57108d8cb63d1217fcf67d908093c' +readonly DOCKER_IMAGE_ID='sha256:ab889141f07b886f02ca3ec664341d7dfada94826c5538842b795b005bc1a417' # Do not modify manually. This value is automatically updated by ./scripts/docker_push . -readonly DOCKER_IMAGE_REPO_DIGEST='gcr.io/oak-ci/oak@sha256:dab7783bd933d187035c85a4621006f723056792a324b524dad41404625362c1' +readonly DOCKER_IMAGE_REPO_DIGEST='gcr.io/oak-ci/oak@sha256:8189809db8f834acb9c56c71f7a80e5ed00f8057ea3ac014b771443356534b1d' readonly SERVER_DOCKER_IMAGE_NAME='gcr.io/oak-ci/oak-server' diff --git a/third_party/ring/.github/workflows/ci.yml b/third_party/ring/.github/workflows/ci.yml index bc8586e72f6..df22f1a157d 100644 --- a/third_party/ring/.github/workflows/ci.yml +++ b/third_party/ring/.github/workflows/ci.yml @@ -552,3 +552,55 @@ jobs: directory: ./target/${{ matrix.target }}/debug/coverage/reports fail_ci_if_error: true verbose: true + + # The x86_64-unknown-uefi targets doesn't have std crate. + # It can only be compiled under `no_std`. + test_uefi: + # Don't run duplicate `push` jobs for the repo owner's PRs. + if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository + + runs-on: ${{ matrix.host_os }} + + strategy: + matrix: + features: + - # Default + target: + - x86_64-unknown-uefi + + mode: + - # debug + - --release + + # Only nightly support no std build. + rust_channel: + - nightly + + host_os: + - windows-latest + - ubuntu-18.04 + + steps: + - if: ${{ contains(matrix.host_os, 'ubuntu') }} + run: sudo apt-get update -y + + - uses: briansmith/actions-checkout@v2 + with: + persist-credentials: false + + - if: ${{ !contains(matrix.host_os, 'windows') }} + run: mk/install-build-tools.sh --target=${{ matrix.target }} ${{ matrix.features }} + + - if: ${{ contains(matrix.host_os, 'windows') }} + run: ./mk/install-build-tools.ps1 + + - uses: briansmith/toolchain@v1 + with: + toolchain: nightly + override: true + components: rust-src + + # Currently, there is no 'rust-std' for target 'x86_64-unknown-uefi'. + # Build-only approach for now. + # TODO: no std tests + - run: mk/cargo.sh build -Zbuild-std="core,alloc" --target=${{ matrix.target }} diff --git a/third_party/ring/Cargo.toml b/third_party/ring/Cargo.toml index 97071e3a4ce..81b800b51f9 100644 --- a/third_party/ring/Cargo.toml +++ b/third_party/ring/Cargo.toml @@ -83,6 +83,7 @@ include = [ "crypto/fipsmodule/modes/asm/ghash-x86.pl", "crypto/fipsmodule/modes/asm/ghash-x86_64.pl", "crypto/fipsmodule/modes/asm/ghashv8-armx.pl", + "crypto/fipsmodule/rand/asm/rdrand-x86_64.pl", "crypto/fipsmodule/sha/asm/sha256-armv4.pl", "crypto/fipsmodule/sha/asm/sha512-armv4.pl", "crypto/fipsmodule/sha/asm/sha512-armv8.pl", diff --git a/third_party/ring/build.rs b/third_party/ring/build.rs index 46e4355efc9..4e569b42f72 100644 --- a/third_party/ring/build.rs +++ b/third_party/ring/build.rs @@ -64,6 +64,7 @@ const RING_SRCS: &[(&[&str], &str)] = &[ (&[X86_64], "crypto/fipsmodule/ec/asm/p256-x86_64-asm.pl"), (&[X86_64], "crypto/fipsmodule/modes/asm/aesni-gcm-x86_64.pl"), (&[X86_64], "crypto/fipsmodule/modes/asm/ghash-x86_64.pl"), + (&[X86_64], "crypto/fipsmodule/rand/asm/rdrand-x86_64.pl"), (&[X86_64], "crypto/poly1305/poly1305_vec.c"), (&[X86_64], SHA512_X86_64), (&[X86_64], "crypto/cipher_extra/asm/chacha20_poly1305_x86_64.pl"), @@ -222,7 +223,7 @@ const ASM_TARGETS: &[AsmTarget] = &[ preassemble: true, }, AsmTarget { - oss: &[WINDOWS], + oss: &[WINDOWS, UEFI], arch: "x86_64", perlasm_format: "nasm", asm_extension: "asm", @@ -279,6 +280,8 @@ const MACOS_ABI: &[&str] = &["ios", "macos"]; const WINDOWS: &str = "windows"; +const UEFI: &str = "uefi"; + /// Read an environment variable and tell Cargo that we depend on it. /// /// This needs to be used for any environment variable that isn't a standard @@ -391,8 +394,9 @@ fn pregenerate_asm_main() { perlasm(&perlasm_src_dsts, asm_target); if asm_target.preassemble { - // Preassembly is currently only done for Windows targets. - assert_eq!(&asm_target.oss, &[WINDOWS]); + // Preassembly is currently done for Windows and UEFI targets. + assert!(asm_target.oss.contains(&WINDOWS) || asm_target.oss.contains(&UEFI)); + let os = WINDOWS; let srcs = asm_srcs(perlasm_src_dsts); @@ -463,7 +467,7 @@ fn build_c_code( // For Windows we also pregenerate the object files for non-Git builds so // the user doesn't need to install the assembler. - if use_pregenerated && target.os == WINDOWS { + if use_pregenerated && supports_preassembly(&target.arch, &target.os) { asm_srcs = asm_srcs .iter() .map(|src| obj_path(&pregenerated, src.as_path())) @@ -557,7 +561,7 @@ fn compile(p: &Path, target: &Target, include_dir: &Path, out_dir: &Path) -> Str p.to_str().expect("Invalid path").into() } else { let out_file = obj_path(out_dir, p); - let cmd = if target.os != WINDOWS || ext != "asm" { + let cmd = if !supports_preassembly(&target.arch, &target.os) || ext != "asm" { cc(p, ext, target, include_dir, &out_file) } else { nasm(p, &target.arch, include_dir, &out_file) @@ -605,6 +609,7 @@ fn cc(file: &Path, ext: &str, target: &Target, include_dir: &Path, out_file: &Pa && target.os != "redox" && target.os != "windows" && target.arch != "wasm32" + && target.os != UEFI { let _ = c.flag("-fstack-protector"); } @@ -630,17 +635,25 @@ fn cc(file: &Path, ext: &str, target: &Target, include_dir: &Path, out_file: &Pa } } + // UEFI is a baremental freestanding environment without stdlib. + let freestanding = target.os == UEFI; + // Allow cross-compiling without a target sysroot for these targets. // // poly1305_vec.c requires which requires . if (target.arch == "wasm32" && target.os == "unknown") || (target.os == "linux" && target.is_musl && target.arch != "x86_64") + || freestanding { if let Ok(compiler) = c.try_get_compiler() { // TODO: Expand this to non-clang compilers in 0.17.0 if practical. if compiler.is_like_clang() { let _ = c.flag("-nostdlibinc"); let _ = c.define("RING_CORE_NOSTDLIBINC", "1"); + + if freestanding { + let _ = c.flag("-ffreestanding"); + } } } } @@ -683,7 +696,10 @@ fn nasm(file: &Path, arch: &str, include_dir: &Path, out_file: &Path) -> Command std::path::MAIN_SEPARATOR, ))); - let mut c = Command::new("./target/tools/windows/nasm/nasm"); + let mut c = Command::new(&get_command( + "NASM_EXECUTABLE", + "./target/tools/windows/nasm/nasm", + )); let _ = c .arg("-o") .arg(out_file.to_str().expect("Invalid path")) @@ -920,6 +936,8 @@ fn prefix_all_symbols(pp: char, prefix_prefix: &str, prefix: &str) -> String { "CRYPTO_poly1305_init_neon", "CRYPTO_poly1305_update", "CRYPTO_poly1305_update_neon", + "CRYPTO_rdrand", + "CRYPTO_rdrand_multiple8_buf", "ChaCha20_ctr32", "LIMBS_add_mod", "LIMBS_are_even", @@ -1030,3 +1048,9 @@ fn prefix_all_symbols(pp: char, prefix_prefix: &str, prefix: &str) -> String { out } + +fn supports_preassembly(arch: &str, os: &str) -> bool { + ASM_TARGETS.iter().any(|asm_target| { + asm_target.preassemble && asm_target.arch == arch && asm_target.oss.contains(&os) + }) +} diff --git a/third_party/ring/crypto/fipsmodule/rand/asm/rdrand-x86_64.pl b/third_party/ring/crypto/fipsmodule/rand/asm/rdrand-x86_64.pl new file mode 100644 index 00000000000..ac442a95b84 --- /dev/null +++ b/third_party/ring/crypto/fipsmodule/rand/asm/rdrand-x86_64.pl @@ -0,0 +1,87 @@ +#!/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. */ + +use strict; + +my $flavour = shift; +my $output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +my $win64 = 0; +$win64 = 1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; +my $dir = $1; +my $xlate; +( $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; + +my ($out, $len, $tmp1, $tmp2) = $win64 ? ("%rcx", "%rdx", "%r8", "%r9") + : ("%rdi", "%rsi", "%rdx", "%rcx"); + +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,\@abi-omnipotent +.align 16 +CRYPTO_rdrand: +.cfi_startproc + xorq %rax, %rax + rdrand $tmp1 + # An add-with-carry of zero effectively sets %rax to the carry flag. + adcq %rax, %rax + movq $tmp1, 0($out) + retq +.cfi_endproc +.size CRYPTO_rdrand,.-CRYPTO_rdrand + +# 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,\@abi-omnipotent +.align 16 +CRYPTO_rdrand_multiple8_buf: +.cfi_startproc + test $len, $len + jz .Lout + movq \$8, $tmp1 +.Lloop: + rdrand $tmp2 + jnc .Lerr + movq $tmp2, 0($out) + addq $tmp1, $out + subq $tmp1, $len + jnz .Lloop +.Lout: + movq \$1, %rax + retq +.Lerr: + xorq %rax, %rax + retq +.cfi_endproc +.size CRYPTO_rdrand_multiple8_buf,.-CRYPTO_rdrand_multiple8_buf +___ + +close STDOUT or die "error closing STDOUT: $!"; # flush diff --git a/third_party/ring/mk/cargo.sh b/third_party/ring/mk/cargo.sh index d6f1acdbd9b..f1780010fea 100755 --- a/third_party/ring/mk/cargo.sh +++ b/third_party/ring/mk/cargo.sh @@ -97,6 +97,11 @@ case $target in export CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_RUSTFLAGS="$rustflags_self_contained" fi ;; + x86_64-unknown-uefi) + export CC_x86_64_unknown_uefi=clang-$llvm_version + export AR_x86_64_unknown_uefi=llvm-ar-$llvm_version + export NASM_EXECUTABLE=nasm + ;; wasm32-unknown-unknown) # The first two are only needed for when the "wasm_c" feature is enabled. export CC_wasm32_unknown_unknown=clang-$llvm_version diff --git a/third_party/ring/mk/install-build-tools.sh b/third_party/ring/mk/install-build-tools.sh index 947dc4fdf36..f1c08da0654 100755 --- a/third_party/ring/mk/install-build-tools.sh +++ b/third_party/ring/mk/install-build-tools.sh @@ -65,6 +65,11 @@ case $target in --target=i686-unknown-linux-musl|--target=x86_64-unknown-linux-musl) use_clang=1 ;; +--target=x86_64-unknown-uefi) + use_clang=1 + install_packages \ + nasm + ;; --target=wasm32-unknown-unknown) # The version of wasm-bindgen-cli must match the wasm-bindgen version. wasm_bindgen_version=$(cargo metadata --format-version 1 | jq -r '.packages | map(select( .name == "wasm-bindgen")) | map(.version) | .[0]') diff --git a/third_party/ring/src/rand.rs b/third_party/ring/src/rand.rs index e7ebece2162..4377b0699de 100644 --- a/third_party/ring/src/rand.rs +++ b/third_party/ring/src/rand.rs @@ -143,6 +143,10 @@ impl RandomlyConstructable for T where T: self::sealed::RandomlyConstructable /// random number generation. /// /// [`getrandom`]: http://man7.org/linux/man-pages/man2/getrandom.2.html +/// +/// On UEFI, `fill` is implemented using `CRYPTO_rdrand` +/// & `CRYPTO_rdrand_multiple8_buf` which provided by BoringSSL. +/// #[derive(Clone, Debug)] pub struct SystemRandom(()); @@ -196,6 +200,9 @@ use self::darwin::fill as fill_impl; #[cfg(any(target_os = "fuchsia"))] use self::fuchsia::fill as fill_impl; +#[cfg(any(target_os = "uefi"))] +use self::uefi::fill as fill_impl; + #[cfg(any(target_os = "android", target_os = "linux"))] mod sysrand_chunk { use crate::{c, error}; @@ -420,3 +427,66 @@ mod fuchsia { fn zx_cprng_draw(buffer: *mut u8, length: usize); } } + +#[cfg(any(target_os = "uefi"))] +mod uefi { + use crate::error; + + pub fn fill(dest: &mut [u8]) -> Result<(), error::Unspecified> { + fill_impl(dest) + } + + #[cfg(not(any(target_arch = "x86_64")))] + fn fill_impl(dest: &mut [u8]) -> Result<(), error::Unspecified> { + Err(error::Unspecified) + } + + #[cfg(any(target_arch = "x86_64"))] + fn fill_impl(dest: &mut [u8]) -> Result<(), error::Unspecified> { + fn is_avaiable() -> bool { + // TODO(xiaoyuxlu): use cpu::intel::RDRAND.avaiable when cpu.rs updated + // https://github.com/briansmith/ring/pull/1406#discussion_r720394928 + // Current implementation may cause problem on AMD cpu. REF: + // https://github.com/nagisa/rust_rdrand/blob/f2fdd528a6103c946a2e9d0961c0592498b36493/src/lib.rs#L161 + prefixed_extern! { + static mut OPENSSL_ia32cap_P: [u32; 4]; + } + const FLAG: u32 = 1 << 30; + unsafe { OPENSSL_ia32cap_P[1] & FLAG == FLAG } + } + + // We must make sure current cpu support `rdrand` + if !is_avaiable() { + return Err(error::Unspecified); + } + + use crate::c; + prefixed_extern! { + fn CRYPTO_rdrand_multiple8_buf(buffer: *mut u8, length: c::size_t) -> c::int; + } + prefixed_extern! { + fn CRYPTO_rdrand(dest: *mut u8) -> c::int; + } + + let len = dest.len(); + let len_multiple8 = len & (!7usize); + let remainder = len - len_multiple8; + + let mut res = 1; + if res != 0 && len_multiple8 != 0 { + res = unsafe { CRYPTO_rdrand_multiple8_buf(dest.as_mut_ptr(), len_multiple8) }; + } + if res != 0 && remainder != 0 { + let mut rand_buf = [0u8; 8]; + res = unsafe { CRYPTO_rdrand(rand_buf.as_mut_ptr()) }; + if res != 0 { + dest[len_multiple8..].copy_from_slice(&rand_buf[..remainder]); + } + } + if res == 1 { + Ok(()) + } else { + Err(error::Unspecified) + } + } +}