1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
|
use std::env;
use std::fs;
use std::io::{self, Write};
use std::path::PathBuf;
use std::process::exit;
fn main() {
crypto_backends_sanity_check();
include_openssl_conf();
lalrpop::Configuration::new().use_cargo_dir_conventions().process().unwrap();
include_test_data().unwrap();
}
/// Optionally include configuration passed from openssl-sys build
/// script. This configuration is then exposed as a set of `osslconf`
/// parameters and is used by OpenSSL backend to enable or disable
/// algorithms available by the current environment.
fn include_openssl_conf() {
if let Ok(vars) = env::var("DEP_OPENSSL_CONF") {
for var in vars.split(',') {
println!("cargo:rustc-cfg=osslconf=\"{}\"", var);
}
}
}
/// Builds the index of the test data for use with the `::tests`
/// module.
fn include_test_data() -> io::Result<()> {
let cwd = env::current_dir()?;
let mut sink = fs::File::create(
PathBuf::from(env::var_os("OUT_DIR").unwrap())
.join("tests.index.rs.inc")).unwrap();
writeln!(&mut sink, "{{")?;
let mut dirs = vec![PathBuf::from("tests/data")];
while let Some(dir) = dirs.pop() {
println!("rerun-if-changed={}", dir.to_str().unwrap());
for entry in fs::read_dir(dir).unwrap() {
let entry = entry?;
let path = entry.path();
if path.is_file() {
writeln!(
&mut sink, " add!({:?}, {:?});",
path.components().skip(2)
.map(|c| c.as_os_str().to_str().expect("valid UTF-8"))
.collect::<Vec<_>>().join("/"),
cwd.join(path))?;
} else if path.is_dir() {
dirs.push(path.clone());
}
}
}
writeln!(&mut sink, "}}")?;
Ok(())
}
fn crypto_backends_sanity_check() {
#[allow(dead_code)]
struct Backend {
name: &'static str,
production_ready: bool,
constant_time: bool,
}
let backends = vec![
(cfg!(all(feature = "crypto-nettle",
not(all(feature = "__implicit-crypto-backend-for-tests",
any(feature = "crypto-openssl",
feature = "crypto-botan",
feature = "crypto-botan2",
feature = "crypto-fuzzing",
feature = "crypto-rust"))))),
Backend {
name: "Nettle",
production_ready: true,
constant_time: true,
}),
(cfg!(all(feature = "crypto-cng",
not(all(feature = "__implicit-crypto-backend-for-tests",
any(feature = "crypto-nettle",
feature = "crypto-openssl",
feature = "crypto-botan",
feature = "crypto-botan2",
feature = "crypto-fuzzing",
feature = "crypto-rust"))))),
Backend {
name: "Windows CNG",
production_ready: true,
constant_time: true,
}),
(cfg!(feature = "crypto-rust"),
Backend {
name: "RustCrypto",
production_ready: false,
constant_time: false,
}),
(cfg!(feature = "crypto-openssl"),
Backend {
name: "OpenSSL",
production_ready: true,
constant_time: true,
}),
(cfg!(feature = "crypto-botan"),
Backend {
name: "Botan",
production_ready: true,
constant_time: true,
}),
(cfg!(feature = "crypto-botan2"),
Backend {
name: "Botan",
production_ready: true,
constant_time: true,
}),
(cfg!(feature = "crypto-fuzzing"),
Backend {
name: "Fuzzing",
production_ready: false,
constant_time: false,
}),
].into_iter().filter_map(|(selected, backend)| {
if selected { Some(backend) } else { None }
}).collect::<Vec<_>>();
match backends.len() {
0 => {
eprintln!("No cryptographic backend selected.
Sequoia requires a cryptographic backend. This backend is selected at compile
time using feature flags.
See https://crates.io/crates/sequoia-openpgp#crypto-backends");
exit(1);
},
1 => {
eprintln!("Selected cryptographic backend: {}", backends[0].name);
},
_ => {
eprintln!("Multiple cryptographic backends selected.
Sequoia requires exactly one cryptographic backend. This backend is
selected at compile time using feature flags.
Unfortunately, you have selected multiple backends:
{}
See https://crates.io/crates/sequoia-openpgp#crypto-backends",
backends.iter().map(|b| b.name).collect::<Vec<_>>().join(", "));
exit(1);
},
}
// We now have exactly one backend.
assert_eq!(backends.len(), 1);
let backend = &backends[0];
// Check its properties.
if ! (backend.production_ready
|| cfg!(feature = "allow-experimental-crypto"))
{
eprintln!("
The cryptographic backend {} is not considered production ready.
If you know what you are doing, you can opt-in to using experimental
cryptographic backends using the feature flag
allow-experimental-crypto
See https://crates.io/crates/sequoia-openpgp#crypto-backends",
backend.name);
exit(1);
}
if ! (backend.constant_time
|| cfg!(feature = "allow-variable-time-crypto"))
{
eprintln!("
The cryptographic backend {} does not provide constant-time
operations. This has the potential of leaking cryptographic secrets,
enable attackers to forge signatures, or cause other mayhem.
If you are not using Sequoia in an interactive setting, using
variable-time cryptographic operations is probably safe.
If you know what you are doing, you can opt-in to using variable-time
cryptographic operations using the feature flag
allow-variable-time-crypto
See https://crates.io/crates/sequoia-openpgp#crypto-backends",
backend.name);
exit(1);
}
}
|