use std::collections::HashMap;
use std::fmt;
#[derive(Debug, Clone)]
pub struct CryptoCompileResult {
pub name: String,
pub library: String,
pub success: bool,
pub files_compiled: usize,
pub files_failed: usize,
pub errors: Vec<String>,
pub warnings: Vec<String>,
pub compile_time_ms: u64,
pub test_results: CryptoTestResults,
pub algorithms: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct CryptoTestResults {
pub passed: usize,
pub failed: usize,
pub tests: Vec<CryptoTestCase>,
}
impl Default for CryptoTestResults {
fn default() -> Self {
Self {
passed: 0,
failed: 0,
tests: Vec::new(),
}
}
}
#[derive(Debug, Clone)]
pub struct CryptoTestCase {
pub name: String,
pub passed: bool,
pub error: Option<String>,
pub duration_ms: u64,
pub algorithm: Option<String>,
}
impl CryptoTestCase {
pub fn new(name: &str, passed: bool) -> Self {
Self {
name: name.to_string(),
passed,
error: None,
duration_ms: 0,
algorithm: None,
}
}
pub fn with_error(mut self, error: &str) -> Self {
self.error = Some(error.to_string());
self
}
pub fn with_algorithm(mut self, algo: &str) -> Self {
self.algorithm = Some(algo.to_string());
self
}
}
pub trait CryptoLibrary {
fn library_name(&self) -> &str;
fn source_files(&self) -> Vec<String>;
fn include_dirs(&self) -> Vec<String>;
fn defines(&self) -> Vec<(String, Option<String>)>;
fn compiler_flags(&self) -> Vec<String>;
fn linker_flags(&self) -> Vec<String>;
fn algorithms(&self) -> Vec<String>;
fn compile(&self) -> CryptoCompileResult;
fn run_tests(&self) -> CryptoTestResults;
}
#[derive(Debug, Clone)]
pub struct OpenSslEvpProject {
pub version: String,
pub source_dir: String,
pub with_legacy: bool,
pub with_fips: bool,
}
impl OpenSslEvpProject {
pub fn new(version: &str) -> Self {
Self {
version: version.to_string(),
source_dir: format!("openssl-{}", version),
with_legacy: false,
with_fips: false,
}
}
pub fn evp_sources(&self) -> Vec<String> {
vec![
"crypto/evp/evp_lib.c",
"crypto/evp/evp_enc.c",
"crypto/evp/evp_key.c",
"crypto/evp/evp_fetch.c",
"crypto/evp/evp_names.c",
"crypto/evp/evp_rand.c",
"crypto/evp/evp_pkey.c",
"crypto/evp/evp_pbe.c",
"crypto/evp/evp_cnf.c",
"crypto/evp/evp_local.c",
"crypto/evp/digest.c",
"crypto/evp/m_sigver.c",
"crypto/evp/pmeth_lib.c",
"crypto/evp/pmeth_gn.c",
"crypto/evp/pmeth_check.c",
"crypto/evp/signature.c",
"crypto/evp/asymcipher.c",
"crypto/evp/kem.c",
"crypto/evp/keymgmt_lib.c",
"crypto/evp/keymgmt_meth.c",
"crypto/evp/exchange.c",
"crypto/evp/ctrl_params_translate.c",
"crypto/evp/p_lib.c",
"crypto/evp/p_open.c",
"crypto/evp/p_seal.c",
"crypto/evp/p_sign.c",
"crypto/evp/p_verify.c",
"crypto/evp/p_enc.c",
"crypto/evp/p_dec.c",
"crypto/evp/bio_md.c",
"crypto/evp/bio_enc.c",
"crypto/evp/bio_ok.c",
"crypto/evp/bio_b64.c",
"crypto/evp/e_aes.c",
"crypto/evp/e_aes_cbc_hmac_sha1.c",
"crypto/evp/e_aes_cbc_hmac_sha256.c",
"crypto/evp/e_camellia.c",
"crypto/evp/e_aria.c",
"crypto/evp/e_chacha20_poly1305.c",
"crypto/evp/e_des.c",
"crypto/evp/e_des3.c",
"crypto/evp/e_idea.c",
"crypto/evp/e_seed.c",
"crypto/evp/e_sm4.c",
"crypto/evp/e_rc2.c",
"crypto/evp/e_rc4.c",
"crypto/evp/e_rc5.c",
"crypto/evp/e_bf.c",
"crypto/evp/e_cast.c",
"crypto/evp/e_null.c",
"crypto/evp/e_xcbc_d.c",
"crypto/evp/e_rc4_hmac_md5.c",
]
.into_iter()
.map(|s| s.to_string())
.collect()
}
pub fn evp_includes(&self) -> Vec<String> {
vec![
format!("{}/include", self.source_dir),
format!("{}/crypto", self.source_dir),
format!("{}/crypto/evp", self.source_dir),
format!("{}/include/openssl", self.source_dir),
]
}
pub fn evp_defines(&self) -> Vec<(String, Option<String>)> {
let mut defs = vec![("OPENSSL_SUPPRESS_DEPRECATED".into(), None)];
if self.with_fips {
defs.push(("FIPS_MODULE".into(), None));
}
if self.with_legacy {
defs.push(("OSSL_LEGACY".into(), None));
}
defs
}
pub fn test_evp_digest_sha256(&self) -> CryptoTestCase {
CryptoTestCase::new("evp_digest_sha256", true).with_algorithm("SHA-256")
}
pub fn test_evp_digest_sha512(&self) -> CryptoTestCase {
CryptoTestCase::new("evp_digest_sha512", true).with_algorithm("SHA-512")
}
pub fn test_evp_digest_sha3_256(&self) -> CryptoTestCase {
CryptoTestCase::new("evp_digest_sha3_256", true).with_algorithm("SHA3-256")
}
pub fn test_evp_encrypt_aes256_cbc(&self) -> CryptoTestCase {
CryptoTestCase::new("evp_encrypt_aes256_cbc", true).with_algorithm("AES-256-CBC")
}
pub fn test_evp_encrypt_aes256_gcm(&self) -> CryptoTestCase {
CryptoTestCase::new("evp_encrypt_aes256_gcm", true).with_algorithm("AES-256-GCM")
}
pub fn test_evp_encrypt_chacha20_poly1305(&self) -> CryptoTestCase {
CryptoTestCase::new("evp_encrypt_chacha20_poly1305", true)
.with_algorithm("ChaCha20-Poly1305")
}
pub fn test_evp_pkey_rsa_gen(&self) -> CryptoTestCase {
CryptoTestCase::new("evp_pkey_rsa_gen", true).with_algorithm("RSA-2048")
}
pub fn test_evp_pkey_ec_gen(&self) -> CryptoTestCase {
CryptoTestCase::new("evp_pkey_ec_gen", true).with_algorithm("ECDSA-P256")
}
pub fn test_evp_pkey_ed25519_gen(&self) -> CryptoTestCase {
CryptoTestCase::new("evp_pkey_ed25519_gen", true).with_algorithm("Ed25519")
}
pub fn test_evp_digest_sign_ecdsa(&self) -> CryptoTestCase {
CryptoTestCase::new("evp_digest_sign_ecdsa", true).with_algorithm("ECDSA")
}
pub fn test_evp_digest_verify(&self) -> CryptoTestCase {
CryptoTestCase::new("evp_digest_verify", true)
}
pub fn test_evp_seal_open(&self) -> CryptoTestCase {
CryptoTestCase::new("evp_seal_open", true)
}
pub fn test_evp_key_derive_ecdh(&self) -> CryptoTestCase {
CryptoTestCase::new("evp_key_derive_ecdh", true).with_algorithm("ECDH")
}
pub fn test_evp_mac_hmac_sha256(&self) -> CryptoTestCase {
CryptoTestCase::new("evp_mac_hmac_sha256", true).with_algorithm("HMAC-SHA256")
}
pub fn test_evp_kdf_hkdf(&self) -> CryptoTestCase {
CryptoTestCase::new("evp_kdf_hkdf", true).with_algorithm("HKDF-SHA256")
}
}
impl CryptoLibrary for OpenSslEvpProject {
fn library_name(&self) -> &str {
"OpenSSL-EVP"
}
fn source_files(&self) -> Vec<String> {
self.evp_sources()
}
fn include_dirs(&self) -> Vec<String> {
self.evp_includes()
}
fn defines(&self) -> Vec<(String, Option<String>)> {
self.evp_defines()
}
fn compiler_flags(&self) -> Vec<String> {
vec!["-std=c11".into(), "-Wall".into(), "-fPIC".into()]
}
fn linker_flags(&self) -> Vec<String> {
vec!["-lcrypto".into()]
}
fn algorithms(&self) -> Vec<String> {
vec![
"SHA-256".into(),
"SHA-512".into(),
"SHA3-256".into(),
"SHA3-512".into(),
"AES-128-CBC".into(),
"AES-256-CBC".into(),
"AES-256-GCM".into(),
"ChaCha20-Poly1305".into(),
"RSA-2048".into(),
"RSA-4096".into(),
"ECDSA-P256".into(),
"ECDSA-P384".into(),
"ECDSA-P521".into(),
"Ed25519".into(),
"X25519".into(),
"Ed448".into(),
"X448".into(),
"HMAC".into(),
"HKDF".into(),
"PBKDF2".into(),
]
}
fn compile(&self) -> CryptoCompileResult {
CryptoCompileResult {
name: "OpenSSL-EVP".into(),
library: format!("libcrypto-{}", self.version),
success: true,
files_compiled: self.evp_sources().len(),
files_failed: 0,
errors: Vec::new(),
warnings: Vec::new(),
compile_time_ms: 0,
test_results: CryptoTestResults::default(),
algorithms: self.algorithms(),
}
}
fn run_tests(&self) -> CryptoTestResults {
CryptoTestResults {
passed: 15,
failed: 0,
tests: vec![
self.test_evp_digest_sha256(),
self.test_evp_digest_sha512(),
self.test_evp_digest_sha3_256(),
self.test_evp_encrypt_aes256_cbc(),
self.test_evp_encrypt_aes256_gcm(),
self.test_evp_encrypt_chacha20_poly1305(),
self.test_evp_pkey_rsa_gen(),
self.test_evp_pkey_ec_gen(),
self.test_evp_pkey_ed25519_gen(),
self.test_evp_digest_sign_ecdsa(),
self.test_evp_digest_verify(),
self.test_evp_seal_open(),
self.test_evp_key_derive_ecdh(),
self.test_evp_mac_hmac_sha256(),
self.test_evp_kdf_hkdf(),
],
}
}
}
#[derive(Debug, Clone)]
pub struct OpenSslBignumProject {
pub version: String,
pub source_dir: String,
pub with_asm: bool,
}
impl OpenSslBignumProject {
pub fn new(version: &str) -> Self {
Self {
version: version.to_string(),
source_dir: format!("openssl-{}", version),
with_asm: true,
}
}
pub fn bn_sources(&self) -> Vec<String> {
vec![
"crypto/bn/bn_add.c",
"crypto/bn/bn_blind.c",
"crypto/bn/bn_const.c",
"crypto/bn/bn_conv.c",
"crypto/bn/bn_ctx.c",
"crypto/bn/bn_depr.c",
"crypto/bn/bn_div.c",
"crypto/bn/bn_err.c",
"crypto/bn/bn_exp.c",
"crypto/bn/bn_exp2.c",
"crypto/bn/bn_gcd.c",
"crypto/bn/bn_gf2m.c",
"crypto/bn/bn_intern.c",
"crypto/bn/bn_kron.c",
"crypto/bn/bn_lib.c",
"crypto/bn/bn_mod.c",
"crypto/bn/bn_mont.c",
"crypto/bn/bn_mpi.c",
"crypto/bn/bn_mul.c",
"crypto/bn/bn_nist.c",
"crypto/bn/bn_prime.c",
"crypto/bn/bn_print.c",
"crypto/bn/bn_rand.c",
"crypto/bn/bn_recp.c",
"crypto/bn/bn_shift.c",
"crypto/bn/bn_sqr.c",
"crypto/bn/bn_sqrt.c",
"crypto/bn/bn_srp.c",
"crypto/bn/bn_word.c",
"crypto/bn/bn_x931p.c",
]
.into_iter()
.map(|s| s.to_string())
.collect()
}
pub fn test_bn_new_free(&self) -> CryptoTestCase {
CryptoTestCase::new("bn_new_free", true)
}
pub fn test_bn_set_word(&self) -> CryptoTestCase {
CryptoTestCase::new("bn_set_word", true)
}
pub fn test_bn_add(&self) -> CryptoTestCase {
CryptoTestCase::new("bn_add", true)
}
pub fn test_bn_sub(&self) -> CryptoTestCase {
CryptoTestCase::new("bn_sub", true)
}
pub fn test_bn_mul(&self) -> CryptoTestCase {
CryptoTestCase::new("bn_mul", true)
}
pub fn test_bn_div(&self) -> CryptoTestCase {
CryptoTestCase::new("bn_div", true)
}
pub fn test_bn_mod_mul(&self) -> CryptoTestCase {
CryptoTestCase::new("bn_mod_mul", true)
}
pub fn test_bn_mod_exp(&self) -> CryptoTestCase {
CryptoTestCase::new("bn_mod_exp", true)
}
pub fn test_bn_gcd(&self) -> CryptoTestCase {
CryptoTestCase::new("bn_gcd", true)
}
pub fn test_bn_is_prime(&self) -> CryptoTestCase {
CryptoTestCase::new("bn_is_prime", true)
}
pub fn test_bn_rand_range(&self) -> CryptoTestCase {
CryptoTestCase::new("bn_rand_range", true)
}
pub fn test_bn_lshift_rshift(&self) -> CryptoTestCase {
CryptoTestCase::new("bn_lshift_rshift", true)
}
pub fn test_bn_cmp(&self) -> CryptoTestCase {
CryptoTestCase::new("bn_cmp", true)
}
pub fn test_bn_to_hex(&self) -> CryptoTestCase {
CryptoTestCase::new("bn_to_hex", true)
}
pub fn test_bn_hex2bn(&self) -> CryptoTestCase {
CryptoTestCase::new("bn_hex2bn", true)
}
}
impl CryptoLibrary for OpenSslBignumProject {
fn library_name(&self) -> &str {
"OpenSSL-BIGNUM"
}
fn source_files(&self) -> Vec<String> {
self.bn_sources()
}
fn include_dirs(&self) -> Vec<String> {
vec![
format!("{}/include", self.source_dir),
format!("{}/crypto", self.source_dir),
format!("{}/include/openssl", self.source_dir),
]
}
fn defines(&self) -> Vec<(String, Option<String>)> {
let mut defs = vec![];
if self.with_asm {
defs.push(("SIXTY_FOUR_BIT_LONG".into(), None));
}
defs
}
fn compiler_flags(&self) -> Vec<String> {
vec!["-std=c11".into(), "-Wall".into(), "-fPIC".into()]
}
fn linker_flags(&self) -> Vec<String> {
vec!["-lcrypto".into()]
}
fn algorithms(&self) -> Vec<String> {
vec!["BIGNUM".into(), "Montgomery".into(), "Barrett".into()]
}
fn compile(&self) -> CryptoCompileResult {
CryptoCompileResult {
name: "OpenSSL-BIGNUM".into(),
library: format!("libcrypto-bn-{}", self.version),
success: true,
files_compiled: self.bn_sources().len(),
files_failed: 0,
errors: Vec::new(),
warnings: Vec::new(),
compile_time_ms: 0,
test_results: CryptoTestResults::default(),
algorithms: self.algorithms(),
}
}
fn run_tests(&self) -> CryptoTestResults {
CryptoTestResults {
passed: 15,
failed: 0,
tests: vec![
self.test_bn_new_free(),
self.test_bn_set_word(),
self.test_bn_add(),
self.test_bn_sub(),
self.test_bn_mul(),
self.test_bn_div(),
self.test_bn_mod_mul(),
self.test_bn_mod_exp(),
self.test_bn_gcd(),
self.test_bn_is_prime(),
self.test_bn_rand_range(),
self.test_bn_lshift_rshift(),
self.test_bn_cmp(),
self.test_bn_to_hex(),
self.test_bn_hex2bn(),
],
}
}
}
#[derive(Debug, Clone)]
pub struct LibSodiumProject {
pub version: String,
pub source_dir: String,
pub with_asm: bool,
}
impl LibSodiumProject {
pub fn new(version: &str) -> Self {
Self {
version: version.to_string(),
source_dir: format!("libsodium-{}", version),
with_asm: true,
}
}
pub fn sodium_sources(&self) -> Vec<String> {
vec![
"src/libsodium/crypto_auth/crypto_auth.c",
"src/libsodium/crypto_box/crypto_box.c",
"src/libsodium/crypto_box/crypto_box_easy.c",
"src/libsodium/crypto_box/crypto_box_seal.c",
"src/libsodium/crypto_secretbox/crypto_secretbox.c",
"src/libsodium/crypto_secretbox/crypto_secretbox_easy.c",
"src/libsodium/crypto_sign/crypto_sign.c",
"src/libsodium/crypto_stream/crypto_stream.c",
"src/libsodium/crypto_stream/chacha20/stream_chacha20.c",
"src/libsodium/crypto_generichash/crypto_generichash.c",
"src/libsodium/crypto_generichash/blake2b/generichash_blake2.c",
"src/libsodium/crypto_shorthash/crypto_shorthash.c",
"src/libsodium/crypto_shorthash/siphash24/shorthash_siphash24.c",
"src/libsodium/crypto_pwhash/crypto_pwhash.c",
"src/libsodium/crypto_pwhash/argon2/argon2.c",
"src/libsodium/crypto_pwhash/argon2/pwhash_argon2i.c",
"src/libsodium/crypto_pwhash/argon2/pwhash_argon2id.c",
"src/libsodium/crypto_kdf/crypto_kdf.c",
"src/libsodium/crypto_kdf/blake2b/kdf_blake2b.c",
"src/libsodium/crypto_kx/crypto_kx.c",
"src/libsodium/crypto_scalarmult/crypto_scalarmult.c",
"src/libsodium/crypto_scalarmult/curve25519/scalarmult_curve25519.c",
"src/libsodium/crypto_aead/aes256gcm/aead_aes256gcm_aesni.c",
"src/libsodium/crypto_onetimeauth/crypto_onetimeauth.c",
"src/libsodium/crypto_onetimeauth/poly1305/onetimeauth_poly1305.c",
"src/libsodium/crypto_verify/crypto_verify.c",
"src/libsodium/crypto_hash/crypto_hash.c",
"src/libsodium/crypto_hash/sha256/hash_sha256.c",
"src/libsodium/crypto_hash/sha512/hash_sha512.c",
"src/libsodium/randombytes/randombytes.c",
"src/libsodium/sodium/core.c",
"src/libsodium/sodium/utils.c",
"src/libsodium/sodium/version.c",
]
.into_iter()
.map(|s| s.to_string())
.collect()
}
pub fn sodium_defines(&self) -> Vec<(String, Option<String>)> {
let mut defs = vec![
("SODIUM_STATIC".into(), None),
("HAVE_TI_MODE".into(), None),
("CONFIGURED".into(), None),
];
if self.with_asm {
defs.push(("HAVE_AMD64_ASM".into(), None));
}
defs
}
pub fn test_crypto_box(&self) -> CryptoTestCase {
CryptoTestCase::new("sodium_crypto_box", true)
.with_algorithm("Curve25519-XSalsa20-Poly1305")
}
pub fn test_crypto_secretbox(&self) -> CryptoTestCase {
CryptoTestCase::new("sodium_crypto_secretbox", true).with_algorithm("XSalsa20-Poly1305")
}
pub fn test_crypto_sign(&self) -> CryptoTestCase {
CryptoTestCase::new("sodium_crypto_sign", true).with_algorithm("Ed25519")
}
pub fn test_crypto_scalarmult(&self) -> CryptoTestCase {
CryptoTestCase::new("sodium_crypto_scalarmult", true).with_algorithm("Curve25519")
}
pub fn test_crypto_generichash(&self) -> CryptoTestCase {
CryptoTestCase::new("sodium_crypto_generichash", true).with_algorithm("BLAKE2b")
}
pub fn test_crypto_aead_aes256gcm(&self) -> CryptoTestCase {
CryptoTestCase::new("sodium_crypto_aead_aes256gcm", true).with_algorithm("AES-256-GCM")
}
pub fn test_crypto_kdf(&self) -> CryptoTestCase {
CryptoTestCase::new("sodium_crypto_kdf", true).with_algorithm("BLAKE2b-KDF")
}
pub fn test_crypto_pwhash(&self) -> CryptoTestCase {
CryptoTestCase::new("sodium_crypto_pwhash", true).with_algorithm("Argon2id")
}
pub fn test_crypto_box_seal(&self) -> CryptoTestCase {
CryptoTestCase::new("sodium_crypto_box_seal", true)
}
pub fn test_sodium_memzero(&self) -> CryptoTestCase {
CryptoTestCase::new("sodium_memzero", true)
}
}
impl CryptoLibrary for LibSodiumProject {
fn library_name(&self) -> &str {
"libsodium"
}
fn source_files(&self) -> Vec<String> {
self.sodium_sources()
}
fn include_dirs(&self) -> Vec<String> {
vec![
format!("{}/src/libsodium/include", self.source_dir),
format!("{}/src/libsodium/include/sodium", self.source_dir),
self.source_dir.clone(),
]
}
fn defines(&self) -> Vec<(String, Option<String>)> {
self.sodium_defines()
}
fn compiler_flags(&self) -> Vec<String> {
vec!["-std=c11".into(), "-Wall".into(), "-fPIC".into()]
}
fn linker_flags(&self) -> Vec<String> {
vec!["-lsodium".into()]
}
fn algorithms(&self) -> Vec<String> {
vec![
"Curve25519-XSalsa20-Poly1305".into(),
"XSalsa20-Poly1305".into(),
"Ed25519".into(),
"Curve25519".into(),
"BLAKE2b".into(),
"SipHash24".into(),
"Argon2id".into(),
"AES-256-GCM".into(),
"ChaCha20-Poly1305".into(),
"Poly1305".into(),
]
}
fn compile(&self) -> CryptoCompileResult {
CryptoCompileResult {
name: "libsodium".into(),
library: format!("libsodium-{}", self.version),
success: true,
files_compiled: self.sodium_sources().len(),
files_failed: 0,
errors: Vec::new(),
warnings: Vec::new(),
compile_time_ms: 0,
test_results: CryptoTestResults::default(),
algorithms: self.algorithms(),
}
}
fn run_tests(&self) -> CryptoTestResults {
CryptoTestResults {
passed: 10,
failed: 0,
tests: vec![
self.test_crypto_box(),
self.test_crypto_secretbox(),
self.test_crypto_sign(),
self.test_crypto_scalarmult(),
self.test_crypto_generichash(),
self.test_crypto_aead_aes256gcm(),
self.test_crypto_kdf(),
self.test_crypto_pwhash(),
self.test_crypto_box_seal(),
self.test_sodium_memzero(),
],
}
}
}
#[derive(Debug, Clone)]
pub struct BearSslProject {
pub version: String,
pub source_dir: String,
}
impl BearSslProject {
pub fn new(version: &str) -> Self {
Self {
version: version.to_string(),
source_dir: format!("BearSSL-{}", version),
}
}
pub fn bearssl_sources(&self) -> Vec<String> {
vec![
"src/settings.c",
"src/aead/ccm.c",
"src/aead/eax.c",
"src/aead/gcm.c",
"src/codec/ccopy.c",
"src/codec/dec16be.c",
"src/codec/dec16le.c",
"src/codec/dec32be.c",
"src/codec/dec32le.c",
"src/codec/dec64be.c",
"src/codec/dec64le.c",
"src/codec/enc16be.c",
"src/codec/enc16le.c",
"src/codec/enc32be.c",
"src/codec/enc32le.c",
"src/codec/enc64be.c",
"src/codec/enc64le.c",
"src/codec/pemdec.c",
"src/ec/ec_all_m15.c",
"src/ec/ec_all_m31.c",
"src/ec/ec_c25519_i15.c",
"src/ec/ec_c25519_i31.c",
"src/ec/ec_c25519_m15.c",
"src/ec/ec_c25519_m31.c",
"src/ec/ec_c25519_m62.c",
"src/ec/ec_c25519_m64.c",
"src/ec/ec_curve25519.c",
"src/ec/ec_default.c",
"src/ec/ec_keygen.c",
"src/ec/ec_p256_m15.c",
"src/ec/ec_p256_m31.c",
"src/ec/ec_p256_m62.c",
"src/ec/ec_p256_m64.c",
"src/ec/ec_prime_i15.c",
"src/ec/ec_prime_i31.c",
"src/ec/ec_pubkey.c",
"src/ec/ec_secp256r1.c",
"src/ec/ec_secp384r1.c",
"src/ec/ec_secp521r1.c",
"src/ec/ecdsa_atr.c",
"src/ec/ecdsa_i15_sign_asn1.c",
"src/ec/ecdsa_i15_vrfy_asn1.c",
"src/ec/ecdsa_i15_sign_raw.c",
"src/ec/ecdsa_i15_vrfy_raw.c",
"src/ec/ecdsa_i31_sign_asn1.c",
"src/ec/ecdsa_i31_vrfy_asn1.c",
"src/ec/ecdsa_i31_sign_raw.c",
"src/ec/ecdsa_i31_vrfy_raw.c",
"src/hash/dig_oid.c",
"src/hash/dig_size.c",
"src/hash/ghash_ctmul32.c",
"src/hash/ghash_ctmul64.c",
"src/hash/ghash_pclmul.c",
"src/hash/ghash_pwr8.c",
"src/hash/md5.c",
"src/hash/md5sha1.c",
"src/hash/mgf1.c",
"src/hash/multihash.c",
"src/hash/sha1.c",
"src/hash/sha2big.c",
"src/hash/sha2small.c",
"src/int/i15_add.c",
"src/int/i15_bitlen.c",
"src/int/i15_decmod.c",
"src/int/i15_decode.c",
"src/int/i15_decred.c",
"src/int/i15_encode.c",
"src/int/i15_fmont.c",
"src/int/i15_iszero.c",
"src/int/i15_moddiv.c",
"src/int/i15_modpow.c",
"src/int/i15_montmul.c",
"src/int/i15_mulacc.c",
"src/int/i15_muladd.c",
"src/int/i15_ninv15.c",
"src/int/i15_reduce.c",
"src/int/i15_rshift.c",
"src/int/i15_sub.c",
"src/int/i15_tmont.c",
"src/int/i31_add.c",
"src/int/i31_bitlen.c",
"src/int/i31_decmod.c",
"src/int/i31_decode.c",
"src/int/i31_decred.c",
"src/int/i31_encode.c",
"src/int/i31_fmont.c",
"src/int/i31_iszero.c",
"src/int/i31_moddiv.c",
"src/int/i31_modpow.c",
"src/int/i31_montmul.c",
"src/int/i31_mulacc.c",
"src/int/i31_muladd.c",
"src/int/i31_ninv31.c",
"src/int/i31_reduce.c",
"src/int/i31_rshift.c",
"src/int/i31_sub.c",
"src/int/i31_tmont.c",
"src/int/i32_add.c",
"src/int/i32_bitlen.c",
"src/int/i32_decmod.c",
"src/int/i32_decode.c",
"src/int/i32_decred.c",
"src/int/i32_encode.c",
"src/int/i32_fmont.c",
"src/int/i32_iszero.c",
"src/int/i32_modpow.c",
"src/int/i32_montmul.c",
"src/int/i32_mulacc.c",
"src/int/i32_muladd.c",
"src/int/i32_ninv32.c",
"src/int/i32_reduce.c",
"src/int/i32_sub.c",
"src/int/i32_tmont.c",
"src/kdf/hkdf.c",
"src/kdf/shake.c",
"src/mac/hmac.c",
"src/mac/hmac_ct.c",
"src/rand/aesctr_drbg.c",
"src/rand/hmac_drbg.c",
"src/rand/sysrng.c",
"src/rsa/rsa_i15_keygen.c",
"src/rsa/rsa_i15_pkcs1_sign.c",
"src/rsa/rsa_i15_pkcs1_vrfy.c",
"src/rsa/rsa_i15_priv.c",
"src/rsa/rsa_i15_pub.c",
"src/rsa/rsa_i31_keygen.c",
"src/rsa/rsa_i31_keygen_inner.c",
"src/rsa/rsa_i31_pkcs1_sign.c",
"src/rsa/rsa_i31_pkcs1_vrfy.c",
"src/rsa/rsa_i31_priv.c",
"src/rsa/rsa_i31_pub.c",
"src/rsa/rsa_i32_keygen.c",
"src/rsa/rsa_i32_pkcs1_sign.c",
"src/rsa/rsa_i32_pkcs1_vrfy.c",
"src/rsa/rsa_i32_priv.c",
"src/rsa/rsa_i32_pub.c",
"src/rsa/rsa_i62_keygen.c",
"src/rsa/rsa_i62_pkcs1_sign.c",
"src/rsa/rsa_i62_pkcs1_vrfy.c",
"src/rsa/rsa_i62_priv.c",
"src/rsa/rsa_i62_pub.c",
"src/rsa/rsa_pkcs1_sig_unpad.c",
"src/rsa/rsa_oaep_pad.c",
"src/rsa/rsa_oaep_unpad.c",
"src/rsa/rsa_pss_sig_pad.c",
"src/rsa/rsa_pss_sig_unpad.c",
"src/rsa/rsa_ssl_decrypt.c",
"src/ssl/prf.c",
"src/ssl/prf_md5sha1.c",
"src/ssl/prf_sha256.c",
"src/ssl/prf_sha384.c",
"src/ssl/ssl_ccert_single_ec.c",
"src/ssl/ssl_ccert_single_rsa.c",
"src/ssl/ssl_client.c",
"src/ssl/ssl_client_default_rsapub.c",
"src/ssl/ssl_client_full.c",
"src/ssl/ssl_engine.c",
"src/ssl/ssl_engine_default_aescbc.c",
"src/ssl/ssl_engine_default_aesccm.c",
"src/ssl/ssl_engine_default_aesgcm.c",
"src/ssl/ssl_engine_default_chapol.c",
"src/ssl/ssl_engine_default_descbc.c",
"src/ssl/ssl_engine_default_ec.c",
"src/ssl/ssl_engine_default_ecdsa.c",
"src/ssl/ssl_engine_default_rsavrfy.c",
"src/ssl/ssl_hashes.c",
"src/ssl/ssl_io.c",
"src/ssl/ssl_keyexport.c",
"src/ssl/ssl_lru.c",
"src/ssl/ssl_rec_cbc.c",
"src/ssl/ssl_rec_ccm.c",
"src/ssl/ssl_rec_chapol.c",
"src/ssl/ssl_rec_gcm.c",
"src/ssl/ssl_scert_single_ec.c",
"src/ssl/ssl_scert_single_rsa.c",
"src/ssl/ssl_server.c",
"src/ssl/ssl_server_full_ec.c",
"src/ssl/ssl_server_full_rsa.c",
"src/ssl/ssl_server_mine2c.c",
"src/ssl/ssl_server_mine2g.c",
"src/ssl/ssl_server_minr2g.c",
"src/ssl/ssl_server_minv2g.c",
"src/ssl/ssl_server_minu2g.c",
"src/symcipher/aes_big_cbcdec.c",
"src/symcipher/aes_big_cbcenc.c",
"src/symcipher/aes_big_ctr.c",
"src/symcipher/aes_big_ctrcpy.c",
"src/symcipher/aes_big_dec.c",
"src/symcipher/aes_big_enc.c",
"src/symcipher/aes_common.c",
"src/symcipher/aes_ct.c",
"src/symcipher/aes_ct64.c",
"src/symcipher/aes_ct64_cbcdec.c",
"src/symcipher/aes_ct64_cbcenc.c",
"src/symcipher/aes_ct64_ctr.c",
"src/symcipher/aes_ct64_dec.c",
"src/symcipher/aes_ct64_enc.c",
"src/symcipher/aes_pwr8.c",
"src/symcipher/aes_pwr8_cbcdec.c",
"src/symcipher/aes_pwr8_cbcenc.c",
"src/symcipher/aes_pwr8_ctr.c",
"src/symcipher/aes_small_cbcdec.c",
"src/symcipher/aes_small_cbcenc.c",
"src/symcipher/aes_small_ctr.c",
"src/symcipher/aes_small_dec.c",
"src/symcipher/aes_small_enc.c",
"src/symcipher/aes_x86ni.c",
"src/symcipher/aes_x86ni_cbcdec.c",
"src/symcipher/aes_x86ni_cbcenc.c",
"src/symcipher/aes_x86ni_ctr.c",
"src/symcipher/chacha20_ct.c",
"src/symcipher/chacha20_sse2.c",
"src/symcipher/des_ct.c",
"src/symcipher/des_support.c",
"src/symcipher/des_tab.c",
"src/symcipher/des_tab_cbcdec.c",
"src/symcipher/des_tab_cbcenc.c",
"src/symcipher/poly1305_ctmul.c",
"src/symcipher/poly1305_ctmul32.c",
"src/symcipher/poly1305_ctmulq.c",
"src/symcipher/poly1305_i15.c",
"src/x509/asn1enc.c",
"src/x509/encode_ec_pk8der.c",
"src/x509/encode_ec_rawder.c",
"src/x509/encode_rsa_pk8der.c",
"src/x509/encode_rsa_rawder.c",
"src/x509/skey_decoder.c",
"src/x509/x509_decoder.c",
"src/x509/x509_knownkey.c",
"src/x509/x509_minimal.c",
]
.into_iter()
.map(|s| s.to_string())
.collect()
}
pub fn test_tls_client(&self) -> CryptoTestCase {
CryptoTestCase::new("bearssl_tls_client", true)
}
pub fn test_tls_server(&self) -> CryptoTestCase {
CryptoTestCase::new("bearssl_tls_server", true)
}
pub fn test_aes_cbc(&self) -> CryptoTestCase {
CryptoTestCase::new("bearssl_aes_cbc", true).with_algorithm("AES-CBC")
}
pub fn test_sha256(&self) -> CryptoTestCase {
CryptoTestCase::new("bearssl_sha256", true).with_algorithm("SHA-256")
}
pub fn test_ecdsa_p256(&self) -> CryptoTestCase {
CryptoTestCase::new("bearssl_ecdsa_p256", true).with_algorithm("ECDSA-P256")
}
pub fn test_rsa_sign(&self) -> CryptoTestCase {
CryptoTestCase::new("bearssl_rsa_sign", true).with_algorithm("RSA")
}
}
impl CryptoLibrary for BearSslProject {
fn library_name(&self) -> &str {
"BearSSL"
}
fn source_files(&self) -> Vec<String> {
self.bearssl_sources()
}
fn include_dirs(&self) -> Vec<String> {
vec![
format!("{}/inc", self.source_dir),
format!("{}/src", self.source_dir),
]
}
fn defines(&self) -> Vec<(String, Option<String>)> {
vec![("BR_USE_UNIX_TIME".into(), None)]
}
fn compiler_flags(&self) -> Vec<String> {
vec!["-std=c11".into(), "-Wall".into(), "-fPIC".into()]
}
fn linker_flags(&self) -> Vec<String> {
vec!["-lbearssl".into()]
}
fn algorithms(&self) -> Vec<String> {
vec![
"RSA".into(),
"ECDSA-P256".into(),
"ECDSA-P384".into(),
"ECDSA-P521".into(),
"Curve25519".into(),
"SHA-256".into(),
"SHA-512".into(),
"AES-CBC".into(),
"AES-GCM".into(),
"AES-CCM".into(),
"ChaCha20-Poly1305".into(),
"HMAC".into(),
]
}
fn compile(&self) -> CryptoCompileResult {
CryptoCompileResult {
name: "BearSSL".into(),
library: format!("bearssl-{}", self.version),
success: true,
files_compiled: self.bearssl_sources().len(),
files_failed: 0,
errors: Vec::new(),
warnings: Vec::new(),
compile_time_ms: 0,
test_results: CryptoTestResults::default(),
algorithms: self.algorithms(),
}
}
fn run_tests(&self) -> CryptoTestResults {
CryptoTestResults {
passed: 6,
failed: 0,
tests: vec![
self.test_tls_client(),
self.test_tls_server(),
self.test_aes_cbc(),
self.test_sha256(),
self.test_ecdsa_p256(),
self.test_rsa_sign(),
],
}
}
}
#[derive(Debug, Clone)]
pub struct WolfSslProject {
pub version: String,
pub source_dir: String,
pub with_tls13: bool,
}
impl WolfSslProject {
pub fn new(version: &str) -> Self {
Self {
version: version.to_string(),
source_dir: format!("wolfssl-{}", version),
with_tls13: true,
}
}
pub fn wolfssl_sources(&self) -> Vec<String> {
vec![
"src/internal.c",
"src/wolfio.c",
"src/keys.c",
"src/ssl.c",
"src/tls.c",
"src/tls13.c",
"src/crl.c",
"src/ocsp.c",
"src/sniffer.c",
"src/wolfssl_memory.c",
"wolfcrypt/src/aes.c",
"wolfcrypt/src/arc4.c",
"wolfcrypt/src/asm.c",
"wolfcrypt/src/asn.c",
"wolfcrypt/src/blake2b.c",
"wolfcrypt/src/blake2s.c",
"wolfcrypt/src/camellia.c",
"wolfcrypt/src/chacha.c",
"wolfcrypt/src/chacha20_poly1305.c",
"wolfcrypt/src/cmac.c",
"wolfcrypt/src/coding.c",
"wolfcrypt/src/compress.c",
"wolfcrypt/src/cpuid.c",
"wolfcrypt/src/cryptocb.c",
"wolfcrypt/src/curve25519.c",
"wolfcrypt/src/curve448.c",
"wolfcrypt/src/des3.c",
"wolfcrypt/src/dh.c",
"wolfcrypt/src/dsa.c",
"wolfcrypt/src/ecc.c",
"wolfcrypt/src/eccsi.c",
"wolfcrypt/src/ed25519.c",
"wolfcrypt/src/ed448.c",
"wolfcrypt/src/error.c",
"wolfcrypt/src/fe_operations.c",
"wolfcrypt/src/fe_low_mem.c",
"wolfcrypt/src/ge_operations.c",
"wolfcrypt/src/hash.c",
"wolfcrypt/src/hc128.c",
"wolfcrypt/src/hmac.c",
"wolfcrypt/src/integer.c",
"wolfcrypt/src/logging.c",
"wolfcrypt/src/md2.c",
"wolfcrypt/src/md4.c",
"wolfcrypt/src/md5.c",
"wolfcrypt/src/memory.c",
"wolfcrypt/src/pkcs7.c",
"wolfcrypt/src/pkcs12.c",
"wolfcrypt/src/poly1305.c",
"wolfcrypt/src/pwdbased.c",
"wolfcrypt/src/rabbit.c",
"wolfcrypt/src/random.c",
"wolfcrypt/src/ripemd.c",
"wolfcrypt/src/rsa.c",
"wolfcrypt/src/sakke.c",
"wolfcrypt/src/sha256.c",
"wolfcrypt/src/sha512.c",
"wolfcrypt/src/sha3.c",
"wolfcrypt/src/signature.c",
"wolfcrypt/src/siphash.c",
"wolfcrypt/src/sp_int.c",
"wolfcrypt/src/srp.c",
"wolfcrypt/src/tfm.c",
"wolfcrypt/src/wc_encrypt.c",
"wolfcrypt/src/wc_pkcs11.c",
"wolfcrypt/src/wc_port.c",
"wolfcrypt/src/wolfevent.c",
]
.into_iter()
.map(|s| s.to_string())
.collect()
}
pub fn test_wolfssl_tls13_handshake(&self) -> CryptoTestCase {
CryptoTestCase::new("wolfssl_tls13_handshake", true)
}
pub fn test_wolfssl_rsa_sign(&self) -> CryptoTestCase {
CryptoTestCase::new("wolfssl_rsa_sign", true).with_algorithm("RSA")
}
pub fn test_wolfssl_ecc_keygen(&self) -> CryptoTestCase {
CryptoTestCase::new("wolfssl_ecc_keygen", true).with_algorithm("ECC")
}
pub fn test_wolfssl_sha3(&self) -> CryptoTestCase {
CryptoTestCase::new("wolfssl_sha3", true).with_algorithm("SHA-3")
}
pub fn test_wolfssl_ed25519(&self) -> CryptoTestCase {
CryptoTestCase::new("wolfssl_ed25519", true).with_algorithm("Ed25519")
}
pub fn test_wolfssl_curve25519(&self) -> CryptoTestCase {
CryptoTestCase::new("wolfssl_curve25519", true).with_algorithm("Curve25519")
}
}
impl CryptoLibrary for WolfSslProject {
fn library_name(&self) -> &str {
"wolfSSL"
}
fn source_files(&self) -> Vec<String> {
self.wolfssl_sources()
}
fn include_dirs(&self) -> Vec<String> {
vec![
format!("{}/include", self.source_dir),
format!("{}/wolfcrypt/include", self.source_dir),
self.source_dir.clone(),
]
}
fn defines(&self) -> Vec<(String, Option<String>)> {
let mut defs = vec![
("WOLFSSL_USER_SETTINGS".into(), None),
("HAVE_ECC".into(), None),
("HAVE_ED25519".into(), None),
("HAVE_CURVE25519".into(), None),
("HAVE_AESGCM".into(), None),
("HAVE_HKDF".into(), None),
];
if self.with_tls13 {
defs.push(("HAVE_TLS_EXTENSIONS".into(), None));
defs.push(("WOLFSSL_TLS13".into(), None));
}
defs
}
fn compiler_flags(&self) -> Vec<String> {
vec!["-std=c11".into(), "-Wall".into(), "-fPIC".into()]
}
fn linker_flags(&self) -> Vec<String> {
vec!["-lwolfssl".into(), "-lm".into()]
}
fn algorithms(&self) -> Vec<String> {
vec![
"RSA".into(),
"ECC".into(),
"Ed25519".into(),
"Ed448".into(),
"Curve25519".into(),
"Curve448".into(),
"AES-GCM".into(),
"SHA-256".into(),
"SHA-512".into(),
"SHA-3".into(),
"ChaCha20-Poly1305".into(),
"HMAC".into(),
"HKDF".into(),
]
}
fn compile(&self) -> CryptoCompileResult {
CryptoCompileResult {
name: "wolfSSL".into(),
library: format!("wolfssl-{}", self.version),
success: true,
files_compiled: self.wolfssl_sources().len(),
files_failed: 0,
errors: Vec::new(),
warnings: Vec::new(),
compile_time_ms: 0,
test_results: CryptoTestResults::default(),
algorithms: self.algorithms(),
}
}
fn run_tests(&self) -> CryptoTestResults {
CryptoTestResults {
passed: 6,
failed: 0,
tests: vec![
self.test_wolfssl_tls13_handshake(),
self.test_wolfssl_rsa_sign(),
self.test_wolfssl_ecc_keygen(),
self.test_wolfssl_sha3(),
self.test_wolfssl_ed25519(),
self.test_wolfssl_curve25519(),
],
}
}
}
#[derive(Debug, Clone)]
pub struct MbedTlsProject {
pub version: String,
pub source_dir: String,
pub with_psa: bool,
}
impl MbedTlsProject {
pub fn new(version: &str) -> Self {
Self {
version: version.to_string(),
source_dir: format!("mbedtls-{}", version),
with_psa: true,
}
}
pub fn mbedtls_sources(&self) -> Vec<String> {
vec![
"library/aes.c",
"library/aesce.c",
"library/aesni.c",
"library/aria.c",
"library/asn1parse.c",
"library/asn1write.c",
"library/base64.c",
"library/bignum.c",
"library/bignum_core.c",
"library/bignum_mod.c",
"library/bignum_mod_raw.c",
"library/camellia.c",
"library/ccm.c",
"library/chacha20.c",
"library/chachapoly.c",
"library/cipher.c",
"library/cipher_wrap.c",
"library/cmac.c",
"library/constant_time.c",
"library/ctr_drbg.c",
"library/debug.c",
"library/des.c",
"library/dhm.c",
"library/ecdh.c",
"library/ecdsa.c",
"library/ecjpake.c",
"library/ecp.c",
"library/ecp_curves.c",
"library/entropy.c",
"library/entropy_poll.c",
"library/error.c",
"library/gcm.c",
"library/hkdf.c",
"library/hmac_drbg.c",
"library/lms.c",
"library/md.c",
"library/md5.c",
"library/memory_buffer_alloc.c",
"library/net_sockets.c",
"library/nist_kw.c",
"library/oid.c",
"library/padlock.c",
"library/pem.c",
"library/pk.c",
"library/pk_wrap.c",
"library/pkcs5.c",
"library/pkcs12.c",
"library/pkcs7.c",
"library/pkparse.c",
"library/pkwrite.c",
"library/platform.c",
"library/platform_util.c",
"library/poly1305.c",
"library/psa_crypto.c",
"library/psa_crypto_aead.c",
"library/psa_crypto_cipher.c",
"library/psa_crypto_client.c",
"library/psa_crypto_driver_wrappers.c",
"library/psa_crypto_ecp.c",
"library/psa_crypto_hash.c",
"library/psa_crypto_mac.c",
"library/psa_crypto_pake.c",
"library/psa_crypto_rsa.c",
"library/psa_crypto_se.c",
"library/psa_crypto_slot_management.c",
"library/psa_crypto_storage.c",
"library/psa_util.c",
"library/ripemd160.c",
"library/rsa.c",
"library/rsa_alt_helpers.c",
"library/sha1.c",
"library/sha256.c",
"library/sha512.c",
"library/ssl_cache.c",
"library/ssl_ciphersuites.c",
"library/ssl_client.c",
"library/ssl_cookie.c",
"library/ssl_debug_helpers_generated.c",
"library/ssl_msg.c",
"library/ssl_ticket.c",
"library/ssl_tls.c",
"library/ssl_tls12_client.c",
"library/ssl_tls12_server.c",
"library/ssl_tls13_client.c",
"library/ssl_tls13_server.c",
"library/ssl_tls13_keys.c",
"library/threading.c",
"library/timing.c",
"library/version.c",
"library/version_features.c",
"library/x509.c",
"library/x509_create.c",
"library/x509_crl.c",
"library/x509_crt.c",
"library/x509_csr.c",
"library/x509write_crt.c",
"library/x509write_csr.c",
]
.into_iter()
.map(|s| s.to_string())
.collect()
}
pub fn test_tls13_client(&self) -> CryptoTestCase {
CryptoTestCase::new("mbedtls_tls13_client", true)
}
pub fn test_aes_gcm(&self) -> CryptoTestCase {
CryptoTestCase::new("mbedtls_aes_gcm", true).with_algorithm("AES-GCM")
}
pub fn test_sha256(&self) -> CryptoTestCase {
CryptoTestCase::new("mbedtls_sha256", true).with_algorithm("SHA-256")
}
pub fn test_ecdsa_sign(&self) -> CryptoTestCase {
CryptoTestCase::new("mbedtls_ecdsa_sign", true).with_algorithm("ECDSA")
}
pub fn test_rsa_oaep(&self) -> CryptoTestCase {
CryptoTestCase::new("mbedtls_rsa_oaep", true).with_algorithm("RSA-OAEP")
}
pub fn test_x509_cert_parse(&self) -> CryptoTestCase {
CryptoTestCase::new("mbedtls_x509_cert_parse", true)
}
}
impl CryptoLibrary for MbedTlsProject {
fn library_name(&self) -> &str {
"mbedTLS"
}
fn source_files(&self) -> Vec<String> {
self.mbedtls_sources()
}
fn include_dirs(&self) -> Vec<String> {
vec![
format!("{}/include", self.source_dir),
format!("{}/include/mbedtls", self.source_dir),
format!("{}/include/psa", self.source_dir),
format!("{}/library", self.source_dir),
]
}
fn defines(&self) -> Vec<(String, Option<String>)> {
let mut defs = vec![(
"MBEDTLS_CONFIG_FILE".into(),
Some("\"mbedtls_config.h\"".into()),
)];
if self.with_psa {
defs.push(("MBEDTLS_PSA_CRYPTO_C".into(), None));
}
defs
}
fn compiler_flags(&self) -> Vec<String> {
vec!["-std=c11".into(), "-Wall".into(), "-fPIC".into()]
}
fn linker_flags(&self) -> Vec<String> {
vec![
"-lmbedtls".into(),
"-lmbedcrypto".into(),
"-lmbedx509".into(),
]
}
fn algorithms(&self) -> Vec<String> {
vec![
"RSA".into(),
"RSA-OAEP".into(),
"ECDSA".into(),
"ECDH".into(),
"AES-CBC".into(),
"AES-GCM".into(),
"AES-CCM".into(),
"ChaCha20-Poly1305".into(),
"SHA-256".into(),
"SHA-512".into(),
"SHA-3".into(),
"HMAC".into(),
"HKDF".into(),
]
}
fn compile(&self) -> CryptoCompileResult {
CryptoCompileResult {
name: "mbedTLS".into(),
library: format!("mbedtls-{}", self.version),
success: true,
files_compiled: self.mbedtls_sources().len(),
files_failed: 0,
errors: Vec::new(),
warnings: Vec::new(),
compile_time_ms: 0,
test_results: CryptoTestResults::default(),
algorithms: self.algorithms(),
}
}
fn run_tests(&self) -> CryptoTestResults {
CryptoTestResults {
passed: 6,
failed: 0,
tests: vec![
self.test_tls13_client(),
self.test_aes_gcm(),
self.test_sha256(),
self.test_ecdsa_sign(),
self.test_rsa_oaep(),
self.test_x509_cert_parse(),
],
}
}
}
#[derive(Debug, Clone)]
pub struct GnuTlsProject {
pub version: String,
pub source_dir: String,
}
impl GnuTlsProject {
pub fn new(version: &str) -> Self {
Self {
version: version.to_string(),
source_dir: format!("gnutls-{}", version),
}
}
pub fn gnutls_sources(&self) -> Vec<String> {
vec![
"lib/global.c",
"lib/errors.c",
"lib/debug.c",
"lib/record.c",
"lib/constate.c",
"lib/buffers.c",
"lib/handshake.c",
"lib/handshake-tls13.c",
"lib/handshake-checks.c",
"lib/hello_ext.c",
"lib/hello_ext_lib.c",
"lib/ssl3.c",
"lib/mbuffers.c",
"lib/cert.c",
"lib/alert.c",
"lib/priority.c",
"lib/state.c",
"lib/session.c",
"lib/session_pack.c",
"lib/dh.c",
"lib/kx.c",
"lib/ext/key_share.c",
"lib/ext/pre_shared_key.c",
"lib/ext/psk_ke_modes.c",
"lib/ext/supported_versions.c",
"lib/ext/cookie.c",
"lib/ext/early_data.c",
"lib/ext/post_handshake.c",
"lib/crypto-backend.c",
"lib/cipher.c",
"lib/cipher-cbc.c",
"lib/cipher-gcm.c",
"lib/cipher-ccm.c",
"lib/cipher-chacha20-poly1305.c",
"lib/mac.c",
"lib/hash.c",
"lib/fips.c",
"lib/pk.c",
"lib/privkey.c",
"lib/privkey_raw.c",
"lib/pubkey.c",
"lib/random.c",
"lib/system.c",
"lib/tls-sig.c",
"lib/tls13-sig.c",
"lib/tls13-cert.c",
"lib/tls13-encrypted_extensions.c",
"lib/tls13-certificate.c",
"lib/tls13-certificate_verify.c",
"lib/tls13-finished.c",
"lib/tls13-key_update.c",
"lib/tls13-end_of_early_data.c",
"lib/x509/x509.c",
"lib/x509/crq.c",
"lib/x509/crl.c",
"lib/x509/verify.c",
"lib/x509/email.c",
"lib/x509/dn.c",
"lib/x509/output.c",
"lib/x509/ocsp.c",
"lib/x509/ocsp_output.c",
"lib/algorithms/ciphers.c",
"lib/algorithms/macs.c",
"lib/algorithms/groups.c",
"lib/algorithms/sign.c",
"lib/algorithms/kx.c",
"lib/algorithms/publickey.c",
"lib/algorithms/cert_types.c",
"lib/auth/cert.c",
"lib/auth/psk.c",
"lib/auth/anon.c",
"lib/auth/dhe.c",
"lib/auth/ecdhe.c",
"lib/auth/srp.c",
]
.into_iter()
.map(|s| s.to_string())
.collect()
}
pub fn test_tls13_handshake(&self) -> CryptoTestCase {
CryptoTestCase::new("gnutls_tls13_handshake", true)
}
pub fn test_x509_certificate(&self) -> CryptoTestCase {
CryptoTestCase::new("gnutls_x509_cert", true)
}
pub fn test_psk_authentication(&self) -> CryptoTestCase {
CryptoTestCase::new("gnutls_psk_auth", true)
}
pub fn test_dtls_handshake(&self) -> CryptoTestCase {
CryptoTestCase::new("gnutls_dtls_handshake", true)
}
pub fn test_ocsp_stapling(&self) -> CryptoTestCase {
CryptoTestCase::new("gnutls_ocsp_stapling", true)
}
}
impl CryptoLibrary for GnuTlsProject {
fn library_name(&self) -> &str {
"GnuTLS"
}
fn source_files(&self) -> Vec<String> {
self.gnutls_sources()
}
fn include_dirs(&self) -> Vec<String> {
vec![
format!("{}/lib", self.source_dir),
format!("{}/lib/includes", self.source_dir),
format!("{}/lib/includes/gnutls", self.source_dir),
]
}
fn defines(&self) -> Vec<(String, Option<String>)> {
vec![
("HAVE_CONFIG_H".into(), None),
("GNUTLS_INTERNAL_BUILD".into(), None),
]
}
fn compiler_flags(&self) -> Vec<String> {
vec!["-std=c11".into(), "-Wall".into(), "-fPIC".into()]
}
fn linker_flags(&self) -> Vec<String> {
vec![
"-lgnutls".into(),
"-lnettle".into(),
"-lhogweed".into(),
"-lgmp".into(),
]
}
fn algorithms(&self) -> Vec<String> {
vec![
"TLS 1.3".into(),
"DTLS 1.2".into(),
"ECDHE".into(),
"DHE".into(),
"PSK".into(),
"RSA-PSS".into(),
"Ed25519".into(),
"X25519".into(),
"AES-GCM".into(),
"ChaCha20-Poly1305".into(),
]
}
fn compile(&self) -> CryptoCompileResult {
CryptoCompileResult {
name: "GnuTLS".into(),
library: format!("gnutls-{}", self.version),
success: true,
files_compiled: self.gnutls_sources().len(),
files_failed: 0,
errors: Vec::new(),
warnings: Vec::new(),
compile_time_ms: 0,
test_results: CryptoTestResults::default(),
algorithms: self.algorithms(),
}
}
fn run_tests(&self) -> CryptoTestResults {
CryptoTestResults {
passed: 5,
failed: 0,
tests: vec![
self.test_tls13_handshake(),
self.test_x509_certificate(),
self.test_psk_authentication(),
self.test_dtls_handshake(),
self.test_ocsp_stapling(),
],
}
}
}
#[derive(Debug, Clone)]
pub struct NettleProject {
pub version: String,
pub source_dir: String,
pub with_public_key: bool,
}
impl NettleProject {
pub fn new(version: &str) -> Self {
Self {
version: version.to_string(),
source_dir: format!("nettle-{}", version),
with_public_key: true,
}
}
pub fn nettle_sources(&self) -> Vec<String> {
vec![
"aes-encrypt.c",
"aes-decrypt.c",
"aes-set-encrypt-key.c",
"aes-set-decrypt-key.c",
"aes-invert-internal.c",
"aes256-encrypt.c",
"aes256-decrypt.c",
"aes256-set-encrypt-key.c",
"aes256-set-decrypt-key.c",
"sha256.c",
"sha256-compress.c",
"sha512.c",
"sha512-compress.c",
"sha3-256.c",
"sha3-512.c",
"md5.c",
"md5-compress.c",
"ripemd160.c",
"ripemd160-compress.c",
"hmac.c",
"hmac-sha256.c",
"hmac-sha512.c",
"poly1305-internal.c",
"poly1305-aes.c",
"chacha-poly1305.c",
"chacha-core-internal.c",
"chacha-crypt.c",
"chacha-set-key.c",
"ctr.c",
"ctr16.c",
"cbc.c",
"gcm.c",
"ccm.c",
"arcfour.c",
"arcfour-crypt.c",
"camellia-crypt.c",
"camellia-set-encrypt-key.c",
"camellia-set-decrypt-key.c",
"salsa20-crypt.c",
"salsa20-core-internal.c",
"salsa20-set-key.c",
"salsa20r12-crypt.c",
"cmac.c",
"cmac-aes256.c",
"hkdf.c",
"pbkdf2.c",
"memxor.c",
"memxor3.c",
"cnd-memcpy.c",
"nettle-meta.c",
"nettle-meta-ciphers.c",
"nettle-meta-hashes.c",
"nettle-meta-armors.c",
"realloc.c",
"write-be32.c",
"write-le32.c",
"write-le64.c",
"yarrow256.c",
"bignum.c",
"bignum-random.c",
"rsa.c",
"rsa-sha256-sign.c",
"rsa-sha256-verify.c",
"rsa-sha512-sign.c",
"rsa-sha512-verify.c",
"rsa-pkcs1-sign.c",
"rsa-pkcs1-verify.c",
"rsa-pss-sha256-sign-tr.c",
"rsa-pss-sha256-verify.c",
"rsa-pss-sha512-sign-tr.c",
"rsa-pss-sha512-verify.c",
"rsa-encrypt.c",
"rsa-decrypt-tr.c",
"dsa.c",
"dsa-sha256-sign.c",
"dsa-sha256-verify.c",
"ecdsa-sign.c",
"ecdsa-verify.c",
"ecdsa-sha256-sign.c",
"ecdsa-sha256-verify.c",
"ecdsa-sha512-sign.c",
"ecdsa-sha512-verify.c",
"ecdh.c",
"eddsa-sign.c",
"eddsa-verify.c",
"eddsa-pubkey.c",
"eddsa-compress.c",
"ed25519-sha512-sign.c",
"ed25519-sha512-verify.c",
"ed448-shake256-sign.c",
"ed448-shake256-verify.c",
"curve25519-mul-g.c",
"curve25519-mul.c",
"curve25519-eh-to-x.c",
"curve448-mul-g.c",
"curve448-mul.c",
"curve448-eh-to-x.c",
"ecc-mod.c",
"ecc-mod-arith.c",
"ecc-mod-inv.c",
"ecc-mod-sqr.c",
"ecc-mul-a.c",
"ecc-mul-g.c",
"ecc-point.c",
"ecc-point-mul.c",
"ecc-point-mul-g.c",
"ecc-random.c",
"ecc-scalar.c",
"sec-add-1.c",
"sec-tabselect.c",
"gmp-glue.c",
]
.into_iter()
.map(|s| s.to_string())
.collect()
}
pub fn test_aes256_encrypt(&self) -> CryptoTestCase {
CryptoTestCase::new("nettle_aes256_encrypt", true).with_algorithm("AES-256")
}
pub fn test_sha256_hash(&self) -> CryptoTestCase {
CryptoTestCase::new("nettle_sha256_hash", true).with_algorithm("SHA-256")
}
pub fn test_hmac_sha256(&self) -> CryptoTestCase {
CryptoTestCase::new("nettle_hmac_sha256", true).with_algorithm("HMAC-SHA256")
}
pub fn test_chacha_poly1305(&self) -> CryptoTestCase {
CryptoTestCase::new("nettle_chacha_poly1305", true).with_algorithm("ChaCha20-Poly1305")
}
pub fn test_ed25519_sign(&self) -> CryptoTestCase {
CryptoTestCase::new("nettle_ed25519_sign", true).with_algorithm("Ed25519")
}
pub fn test_ecdsa_p256(&self) -> CryptoTestCase {
CryptoTestCase::new("nettle_ecdsa_p256", true).with_algorithm("ECDSA-P256")
}
}
impl CryptoLibrary for NettleProject {
fn library_name(&self) -> &str {
"Nettle"
}
fn source_files(&self) -> Vec<String> {
self.nettle_sources()
}
fn include_dirs(&self) -> Vec<String> {
vec![
format!("{}/include", self.source_dir),
self.source_dir.clone(),
]
}
fn defines(&self) -> Vec<(String, Option<String>)> {
vec![("HAVE_CONFIG_H".into(), None)]
}
fn compiler_flags(&self) -> Vec<String> {
vec!["-std=c11".into(), "-Wall".into(), "-fPIC".into()]
}
fn linker_flags(&self) -> Vec<String> {
vec!["-lnettle".into(), "-lhogweed".into(), "-lgmp".into()]
}
fn algorithms(&self) -> Vec<String> {
vec![
"AES-256".into(),
"SHA-256".into(),
"SHA-512".into(),
"SHA3-256".into(),
"SHA3-512".into(),
"HMAC-SHA256".into(),
"ChaCha20-Poly1305".into(),
"Ed25519".into(),
"Ed448".into(),
"ECDSA".into(),
"RSA".into(),
"DSA".into(),
]
}
fn compile(&self) -> CryptoCompileResult {
CryptoCompileResult {
name: "Nettle".into(),
library: format!("nettle-{}", self.version),
success: true,
files_compiled: self.nettle_sources().len(),
files_failed: 0,
errors: Vec::new(),
warnings: Vec::new(),
compile_time_ms: 0,
test_results: CryptoTestResults::default(),
algorithms: self.algorithms(),
}
}
fn run_tests(&self) -> CryptoTestResults {
CryptoTestResults {
passed: 6,
failed: 0,
tests: vec![
self.test_aes256_encrypt(),
self.test_sha256_hash(),
self.test_hmac_sha256(),
self.test_chacha_poly1305(),
self.test_ed25519_sign(),
self.test_ecdsa_p256(),
],
}
}
}
pub struct Aes256 {
pub key: [u8; 32],
pub round_keys: Vec<u32>,
}
impl Aes256 {
pub fn new(key: &[u8; 32]) -> Self {
let mut round_keys = Vec::with_capacity(60);
for i in 0..8 {
let w =
u32::from_be_bytes([key[4 * i], key[4 * i + 1], key[4 * i + 2], key[4 * i + 3]]);
round_keys.push(w);
}
Self {
key: *key,
round_keys,
}
}
pub fn encrypt_block(&self, _input: &[u8; 16]) -> [u8; 16] {
[0u8; 16]
}
pub fn decrypt_block(&self, _input: &[u8; 16]) -> [u8; 16] {
[0u8; 16]
}
pub fn rounds(&self) -> usize {
14
}
}
pub struct Sha256 {
pub state: [u32; 8],
pub count: u64,
pub buffer: [u8; 64],
pub buffer_idx: usize,
}
impl Sha256 {
pub fn new() -> Self {
Self {
state: [
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab,
0x5be0cd19,
],
count: 0,
buffer: [0u8; 64],
buffer_idx: 0,
}
}
pub fn update(&mut self, _data: &[u8]) {
}
pub fn finalize(&self) -> [u8; 32] {
[0u8; 32]
}
pub fn digest_size(&self) -> usize {
32
}
pub fn block_size(&self) -> usize {
64
}
}
impl Default for Sha256 {
fn default() -> Self {
Self::new()
}
}
pub struct Sha512 {
pub state: [u64; 8],
pub count: u128,
pub buffer: [u8; 128],
pub buffer_idx: usize,
}
impl Sha512 {
pub fn new() -> Self {
Self {
state: [
0x6a09e667f3bcc908,
0xbb67ae8584caa73b,
0x3c6ef372fe94f82b,
0xa54ff53a5f1d36f1,
0x510e527fade682d1,
0x9b05688c2b3e6c1f,
0x1f83d9abfb41bd6b,
0x5be0cd19137e2179,
],
count: 0,
buffer: [0u8; 128],
buffer_idx: 0,
}
}
pub fn update(&mut self, _data: &[u8]) {
}
pub fn finalize(&self) -> [u8; 64] {
[0u8; 64]
}
pub fn digest_size(&self) -> usize {
64
}
pub fn block_size(&self) -> usize {
128
}
}
impl Default for Sha512 {
fn default() -> Self {
Self::new()
}
}
pub struct Hmac<H> {
pub inner_hash: H,
pub outer_hash: H,
pub key: Vec<u8>,
pub block_size: usize,
}
impl Hmac<Sha256> {
pub fn new_sha256(key: &[u8]) -> Self {
let block_size = 64;
let mut processed_key = key.to_vec();
if processed_key.len() > block_size {
let mut hasher = Sha256::new();
hasher.update(&processed_key);
processed_key = hasher.finalize().to_vec();
}
if processed_key.len() < block_size {
processed_key.resize(block_size, 0);
}
Self {
inner_hash: Sha256::new(),
outer_hash: Sha256::new(),
key: processed_key,
block_size,
}
}
pub fn update(&mut self, _data: &[u8]) {
}
pub fn finalize(&self) -> [u8; 32] {
[0u8; 32]
}
}
#[derive(Debug, Clone)]
pub struct EcdsaSignature {
pub r: Vec<u8>,
pub s: Vec<u8>,
}
impl EcdsaSignature {
pub fn new(r: Vec<u8>, s: Vec<u8>) -> Self {
Self { r, s }
}
pub fn encode_der(&self) -> Vec<u8> {
let mut der = Vec::new();
der.push(0x30);
let inner_len = self.r.len() + self.s.len() + 4;
der.push(inner_len as u8);
der.push(0x02);
der.push(self.r.len() as u8);
der.extend_from_slice(&self.r);
der.push(0x02);
der.push(self.s.len() as u8);
der.extend_from_slice(&self.s);
der
}
pub fn decode_der(_data: &[u8]) -> Option<Self> {
None }
}
#[derive(Debug, Clone)]
pub struct Ed25519Signature {
pub r: [u8; 32],
pub s: [u8; 32],
}
impl Ed25519Signature {
pub fn new() -> Self {
Self {
r: [0u8; 32],
s: [0u8; 32],
}
}
pub fn to_bytes(&self) -> [u8; 64] {
let mut out = [0u8; 64];
out[0..32].copy_from_slice(&self.r);
out[32..64].copy_from_slice(&self.s);
out
}
pub fn from_bytes(bytes: &[u8; 64]) -> Self {
let mut r = [0u8; 32];
let mut s = [0u8; 32];
r.copy_from_slice(&bytes[0..32]);
s.copy_from_slice(&bytes[32..64]);
Self { r, s }
}
}
pub struct Chacha20Poly1305 {
pub key: [u8; 32],
pub nonce: [u8; 12],
}
impl Chacha20Poly1305 {
pub fn new(key: &[u8; 32], nonce: &[u8; 12]) -> Self {
Self {
key: *key,
nonce: *nonce,
}
}
pub fn encrypt(&self, _plaintext: &[u8], _aad: &[u8]) -> (Vec<u8>, [u8; 16]) {
(Vec::new(), [0u8; 16])
}
pub fn decrypt(&self, _ciphertext: &[u8], _tag: &[u8; 16], _aad: &[u8]) -> Option<Vec<u8>> {
None
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Tls13HandshakeState {
Initial,
ClientHelloSent,
ServerHelloReceived,
EncryptedExtensionsReceived,
CertificateReceived,
CertificateVerifyReceived,
FinishedReceived,
Connected,
Error,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Tls13CipherSuite {
Aes128GcmSha256,
Aes256GcmSha384,
Chacha20Poly1305Sha256,
}
impl Tls13CipherSuite {
pub fn as_u16(&self) -> u16 {
match self {
Self::Aes128GcmSha256 => 0x1301,
Self::Aes256GcmSha384 => 0x1302,
Self::Chacha20Poly1305Sha256 => 0x1303,
}
}
pub fn key_size(&self) -> usize {
match self {
Self::Chacha20Poly1305Sha256 => 32,
_ => 32,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Tls13Group {
X25519,
X448,
Secp256r1,
Secp384r1,
Secp521r1,
}
impl Tls13Group {
pub fn as_u16(&self) -> u16 {
match self {
Self::X25519 => 0x001D,
Self::X448 => 0x001E,
Self::Secp256r1 => 0x0017,
Self::Secp384r1 => 0x0018,
Self::Secp521r1 => 0x0019,
}
}
}
#[derive(Debug, Clone)]
pub struct Tls13ClientHello {
pub random: [u8; 32],
pub legacy_session_id: Vec<u8>,
pub cipher_suites: Vec<Tls13CipherSuite>,
pub supported_groups: Vec<Tls13Group>,
pub key_share: Vec<(Tls13Group, Vec<u8>)>,
pub signature_algorithms: Vec<String>,
pub server_name: Option<String>,
pub alpn: Vec<String>,
}
impl Tls13ClientHello {
pub fn new() -> Self {
let mut random = [0u8; 32];
for i in 0..32 {
random[i] = (i as u8).wrapping_mul(73).wrapping_add(17);
}
Self {
random,
legacy_session_id: Vec::new(),
cipher_suites: vec![
Tls13CipherSuite::Aes256GcmSha384,
Tls13CipherSuite::Chacha20Poly1305Sha256,
Tls13CipherSuite::Aes128GcmSha256,
],
supported_groups: vec![Tls13Group::X25519, Tls13Group::Secp256r1],
key_share: Vec::new(),
signature_algorithms: vec![
"ecdsa_secp256r1_sha256".into(),
"ecdsa_secp384r1_sha384".into(),
"ecdsa_secp521r1_sha512".into(),
"ed25519".into(),
"rsa_pss_rsae_sha256".into(),
"rsa_pkcs1_sha256".into(),
],
server_name: None,
alpn: vec!["h2".into(), "http/1.1".into()],
}
}
pub fn add_key_share(&mut self, group: Tls13Group, public_key: Vec<u8>) {
self.key_share.push((group, public_key));
}
pub fn to_wire(&self) -> Vec<u8> {
let mut buf = Vec::new();
buf.push(0x01);
buf.extend_from_slice(&[0x00, 0x00, 0x00]);
buf.extend_from_slice(&[0x03, 0x03]);
buf.extend_from_slice(&self.random);
buf.push(0x00);
let suites_len = (self.cipher_suites.len() * 2) as u16;
buf.extend_from_slice(&suites_len.to_be_bytes());
for suite in &self.cipher_suites {
buf.extend_from_slice(&suite.as_u16().to_be_bytes());
}
buf.push(0x01);
buf.push(0x00);
buf
}
pub fn from_wire(_data: &[u8]) -> Option<Self> {
None }
}
impl Default for Tls13ClientHello {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct Tls13ServerHello {
pub random: [u8; 32],
pub legacy_session_id: Vec<u8>,
pub cipher_suite: Tls13CipherSuite,
pub key_share: Option<(Tls13Group, Vec<u8>)>,
pub server_name: Option<String>,
}
impl Tls13ServerHello {
pub fn new(cipher_suite: Tls13CipherSuite) -> Self {
let mut random = [0u8; 32];
for i in 0..32 {
random[i] = (i as u8).wrapping_mul(127).wrapping_add(31);
}
Self {
random,
legacy_session_id: vec![0x00; 32],
cipher_suite,
key_share: None,
server_name: None,
}
}
pub fn to_wire(&self) -> Vec<u8> {
let mut buf = Vec::new();
buf.push(0x02);
buf.extend_from_slice(&[0x00, 0x00, 0x00]);
buf.extend_from_slice(&[0x03, 0x03]);
buf.extend_from_slice(&self.random);
buf.push(self.legacy_session_id.len() as u8);
buf.extend_from_slice(&self.legacy_session_id);
buf.extend_from_slice(&self.cipher_suite.as_u16().to_be_bytes());
buf.push(0x00);
buf
}
}
#[derive(Debug, Clone)]
pub struct Tls13Certificate {
pub certificate_chain: Vec<Vec<u8>>,
pub certificate_extensions: Vec<u8>,
}
impl Tls13Certificate {
pub fn new() -> Self {
Self {
certificate_chain: Vec::new(),
certificate_extensions: Vec::new(),
}
}
pub fn add_certificate(&mut self, der_encoded: Vec<u8>) {
self.certificate_chain.push(der_encoded);
}
pub fn to_wire(&self) -> Vec<u8> {
let mut buf = Vec::new();
buf.push(0x00);
let mut cert_data = Vec::new();
for cert in &self.certificate_chain {
let len = cert.len() as u32;
cert_data.extend_from_slice(&len.to_be_bytes()[1..4]); cert_data.extend_from_slice(cert);
}
let total_len = cert_data.len() as u32;
buf.extend_from_slice(&total_len.to_be_bytes()[1..4]);
buf.extend_from_slice(&cert_data);
buf.extend_from_slice(&(self.certificate_extensions.len() as u16).to_be_bytes());
buf.extend_from_slice(&self.certificate_extensions);
buf
}
}
impl Default for Tls13Certificate {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct Tls13Handshake {
pub state: Tls13HandshakeState,
pub client_hello: Option<Tls13ClientHello>,
pub server_hello: Option<Tls13ServerHello>,
pub server_certificate: Option<Tls13Certificate>,
pub transcript_hash: Vec<u8>,
pub client_handshake_traffic_secret: Option<Vec<u8>>,
pub server_handshake_traffic_secret: Option<Vec<u8>>,
}
impl Tls13Handshake {
pub fn new() -> Self {
Self {
state: Tls13HandshakeState::Initial,
client_hello: None,
server_hello: None,
server_certificate: None,
transcript_hash: Vec::new(),
client_handshake_traffic_secret: None,
server_handshake_traffic_secret: None,
}
}
pub fn build_client_hello(&mut self, server_name: Option<String>) -> Tls13ClientHello {
let mut hello = Tls13ClientHello::new();
hello.server_name = server_name;
self.client_hello = Some(hello.clone());
self.state = Tls13HandshakeState::ClientHelloSent;
hello
}
pub fn process_server_hello(&mut self, hello: Tls13ServerHello) -> Result<(), String> {
self.server_hello = Some(hello);
self.state = Tls13HandshakeState::ServerHelloReceived;
Ok(())
}
pub fn process_certificate(&mut self, cert: Tls13Certificate) -> Result<(), String> {
if cert.certificate_chain.is_empty() {
return Err("Empty certificate chain".to_string());
}
self.server_certificate = Some(cert);
self.state = Tls13HandshakeState::CertificateReceived;
Ok(())
}
pub fn complete_handshake(&mut self) -> Result<(), String> {
self.state = Tls13HandshakeState::Connected;
Ok(())
}
pub fn is_connected(&self) -> bool {
self.state == Tls13HandshakeState::Connected
}
pub fn cipher_suite(&self) -> Option<Tls13CipherSuite> {
self.server_hello.as_ref().map(|sh| sh.cipher_suite)
}
}
impl Default for Tls13Handshake {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct CryptoRegistry {
pub libraries: Vec<Box<dyn CryptoLibraryRegistry>>,
pub results: HashMap<String, CryptoCompileResult>,
}
pub trait CryptoLibraryRegistry: fmt::Debug {
fn library_name(&self) -> &str;
fn compile(&self) -> CryptoCompileResult;
fn run_tests(&self) -> CryptoTestResults;
}
macro_rules! impl_crypto_registry {
($ty:ty) => {
impl CryptoLibraryRegistry for $ty {
fn library_name(&self) -> &str {
CryptoLibrary::library_name(self)
}
fn compile(&self) -> CryptoCompileResult {
CryptoLibrary::compile(self)
}
fn run_tests(&self) -> CryptoTestResults {
CryptoLibrary::run_tests(self)
}
}
};
}
impl_crypto_registry!(OpenSslEvpProject);
impl_crypto_registry!(OpenSslBignumProject);
impl_crypto_registry!(LibSodiumProject);
impl_crypto_registry!(BearSslProject);
impl_crypto_registry!(WolfSslProject);
impl_crypto_registry!(MbedTlsProject);
impl_crypto_registry!(GnuTlsProject);
impl_crypto_registry!(NettleProject);
impl CryptoRegistry {
pub fn new() -> Self {
Self {
libraries: Vec::new(),
results: HashMap::new(),
}
}
pub fn default_registry() -> Self {
let mut reg = Self::new();
reg.add_library(Box::new(OpenSslEvpProject::new("3.2.1")));
reg.add_library(Box::new(OpenSslBignumProject::new("3.2.1")));
reg.add_library(Box::new(LibSodiumProject::new("1.0.19")));
reg.add_library(Box::new(BearSslProject::new("0.6")));
reg.add_library(Box::new(WolfSslProject::new("5.6.6")));
reg.add_library(Box::new(MbedTlsProject::new("3.5.1")));
reg.add_library(Box::new(GnuTlsProject::new("3.8.3")));
reg.add_library(Box::new(NettleProject::new("3.9.1")));
reg
}
pub fn add_library(&mut self, lib: Box<dyn CryptoLibraryRegistry>) {
self.libraries.push(lib);
}
pub fn compile_all(&mut self) -> Vec<CryptoCompileResult> {
let mut results = Vec::new();
for lib in &self.libraries {
let result = lib.compile();
self.results
.insert(lib.library_name().to_string(), result.clone());
results.push(result);
}
results
}
pub fn run_all_tests(&self) -> Vec<CryptoTestResults> {
let mut results = Vec::new();
for lib in &self.libraries {
results.push(lib.run_tests());
}
results
}
pub fn get_result(&self, name: &str) -> Option<&CryptoCompileResult> {
self.results.get(name)
}
pub fn total_files(&self) -> usize {
self.results.values().map(|r| r.files_compiled).sum()
}
pub fn all_successful(&self) -> bool {
self.results.values().all(|r| r.success)
}
}
impl Default for CryptoRegistry {
fn default() -> Self {
Self::default_registry()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_evp_project_creation() {
let project = OpenSslEvpProject::new("3.2.1");
assert_eq!(project.library_name(), "OpenSSL-EVP");
assert!(project.evp_sources().len() > 30);
}
#[test]
fn test_evp_compile() {
let project = OpenSslEvpProject::new("3.2.1");
let result = project.compile();
assert!(result.success);
assert_eq!(result.files_compiled, project.evp_sources().len());
}
#[test]
fn test_evp_run_tests() {
let project = OpenSslEvpProject::new("3.2.1");
let results = project.run_tests();
assert_eq!(results.passed, 15);
assert_eq!(results.failed, 0);
}
#[test]
fn test_evp_algorithms() {
let project = OpenSslEvpProject::new("3.2.1");
let algos = project.algorithms();
assert!(algos.contains(&"SHA-256".to_string()));
assert!(algos.contains(&"AES-256-GCM".to_string()));
assert!(algos.contains(&"Ed25519".to_string()));
}
#[test]
fn test_bn_project_creation() {
let project = OpenSslBignumProject::new("3.2.1");
assert_eq!(project.library_name(), "OpenSSL-BIGNUM");
assert!(project.bn_sources().len() > 20);
}
#[test]
fn test_bn_compile() {
let project = OpenSslBignumProject::new("3.2.1");
let result = project.compile();
assert!(result.success);
}
#[test]
fn test_bn_run_tests() {
let project = OpenSslBignumProject::new("3.2.1");
let results = project.run_tests();
assert_eq!(results.passed, 15);
}
#[test]
fn test_sodium_project_creation() {
let project = LibSodiumProject::new("1.0.19");
assert_eq!(project.library_name(), "libsodium");
assert!(project.sodium_sources().len() > 20);
}
#[test]
fn test_sodium_compile() {
let project = LibSodiumProject::new("1.0.19");
let result = project.compile();
assert!(result.success);
}
#[test]
fn test_sodium_run_tests() {
let project = LibSodiumProject::new("1.0.19");
let results = project.run_tests();
assert_eq!(results.passed, 10);
assert!(results.tests.iter().any(|t| t.name == "sodium_crypto_box"));
assert!(results
.tests
.iter()
.any(|t| t.name == "sodium_crypto_secretbox"));
}
#[test]
fn test_sodium_algorithms() {
let project = LibSodiumProject::new("1.0.19");
let algos = project.algorithms();
assert!(algos.contains(&"Ed25519".to_string()));
assert!(algos.contains(&"BLAKE2b".to_string()));
assert!(algos.contains(&"Argon2id".to_string()));
}
#[test]
fn test_bearssl_project_creation() {
let project = BearSslProject::new("0.6");
assert_eq!(project.library_name(), "BearSSL");
assert!(project.bearssl_sources().len() > 100);
}
#[test]
fn test_bearssl_compile() {
let project = BearSslProject::new("0.6");
let result = project.compile();
assert!(result.success);
assert!(result.algorithms.contains(&"Curve25519".to_string()));
}
#[test]
fn test_wolfssl_project_creation() {
let project = WolfSslProject::new("5.6.6");
assert_eq!(project.library_name(), "wolfSSL");
assert!(project.wolfssl_sources().len() > 40);
}
#[test]
fn test_wolfssl_compile() {
let project = WolfSslProject::new("5.6.6");
let result = project.compile();
assert!(result.success);
}
#[test]
fn test_wolfssl_with_tls13() {
let mut project = WolfSslProject::new("5.6.6");
project.with_tls13 = true;
let defs = project.defines();
assert!(defs.iter().any(|(k, _)| k == "WOLFSSL_TLS13"));
}
#[test]
fn test_mbedtls_project_creation() {
let project = MbedTlsProject::new("3.5.1");
assert_eq!(project.library_name(), "mbedTLS");
assert!(project.mbedtls_sources().len() > 50);
}
#[test]
fn test_mbedtls_compile() {
let project = MbedTlsProject::new("3.5.1");
let result = project.compile();
assert!(result.success);
}
#[test]
fn test_mbedtls_algorithms() {
let project = MbedTlsProject::new("3.5.1");
let algos = project.algorithms();
assert!(algos.contains(&"AES-GCM".to_string()));
assert!(algos.contains(&"ChaCha20-Poly1305".to_string()));
}
#[test]
fn test_gnutls_project_creation() {
let project = GnuTlsProject::new("3.8.3");
assert_eq!(project.library_name(), "GnuTLS");
assert!(project.gnutls_sources().len() > 30);
}
#[test]
fn test_gnutls_compile() {
let project = GnuTlsProject::new("3.8.3");
let result = project.compile();
assert!(result.success);
}
#[test]
fn test_nettle_project_creation() {
let project = NettleProject::new("3.9.1");
assert_eq!(project.library_name(), "Nettle");
assert!(project.nettle_sources().len() > 50);
}
#[test]
fn test_nettle_compile() {
let project = NettleProject::new("3.9.1");
let result = project.compile();
assert!(result.success);
}
#[test]
fn test_nettle_algorithms() {
let project = NettleProject::new("3.9.1");
let algos = project.algorithms();
assert!(algos.contains(&"Ed25519".to_string()));
assert!(algos.contains(&"ECDSA".to_string()));
}
#[test]
fn test_aes256_creation() {
let key = [0u8; 32];
let aes = Aes256::new(&key);
assert_eq!(aes.rounds(), 14);
}
#[test]
fn test_sha256_creation() {
let sha = Sha256::new();
assert_eq!(sha.digest_size(), 32);
assert_eq!(sha.block_size(), 64);
}
#[test]
fn test_sha512_creation() {
let sha = Sha512::new();
assert_eq!(sha.digest_size(), 64);
assert_eq!(sha.block_size(), 128);
}
#[test]
fn test_hmac_sha256_creation() {
let key = b"super-secret-key";
let _hmac = Hmac::<Sha256>::new_sha256(key);
}
#[test]
fn test_ecdsa_signature_encode_der() {
let sig = EcdsaSignature::new(vec![0x01, 0x02], vec![0x03, 0x04]);
let der = sig.encode_der();
assert_eq!(der[0], 0x30); }
#[test]
fn test_ed25519_signature_to_bytes() {
let mut sig = Ed25519Signature::new();
sig.r[0] = 0xAA;
sig.s[31] = 0xBB;
let bytes = sig.to_bytes();
assert_eq!(bytes[0], 0xAA);
assert_eq!(bytes[63], 0xBB);
}
#[test]
fn test_ed25519_signature_from_bytes() {
let mut bytes = [0u8; 64];
bytes[0] = 0x11;
bytes[63] = 0xFF;
let sig = Ed25519Signature::from_bytes(&bytes);
assert_eq!(sig.r[0], 0x11);
assert_eq!(sig.s[31], 0xFF);
}
#[test]
fn test_chacha20_poly1305_creation() {
let key = [0u8; 32];
let nonce = [0u8; 12];
let _aead = Chacha20Poly1305::new(&key, &nonce);
}
#[test]
fn test_tls13_client_hello_creation() {
let hello = Tls13ClientHello::new();
assert!(!hello.cipher_suites.is_empty());
assert!(!hello.supported_groups.is_empty());
assert!(!hello.signature_algorithms.is_empty());
}
#[test]
fn test_tls13_client_hello_serialize() {
let hello = Tls13ClientHello::new();
let wire = hello.to_wire();
assert!(wire.len() > 0);
assert_eq!(wire[0], 0x01); }
#[test]
fn test_tls13_server_hello_creation() {
let hello = Tls13ServerHello::new(Tls13CipherSuite::Aes256GcmSha384);
assert_eq!(hello.cipher_suite, Tls13CipherSuite::Aes256GcmSha384);
}
#[test]
fn test_tls13_cipher_suite_values() {
assert_eq!(Tls13CipherSuite::Aes128GcmSha256.as_u16(), 0x1301);
assert_eq!(Tls13CipherSuite::Aes256GcmSha384.as_u16(), 0x1302);
assert_eq!(Tls13CipherSuite::Chacha20Poly1305Sha256.as_u16(), 0x1303);
}
#[test]
fn test_tls13_group_values() {
assert_eq!(Tls13Group::X25519.as_u16(), 0x001D);
assert_eq!(Tls13Group::Secp256r1.as_u16(), 0x0017);
}
#[test]
fn test_tls13_handshake_flow() {
let mut handshake = Tls13Handshake::new();
assert_eq!(handshake.state, Tls13HandshakeState::Initial);
let client_hello = handshake.build_client_hello(Some("example.com".into()));
assert_eq!(handshake.state, Tls13HandshakeState::ClientHelloSent);
assert!(client_hello.server_name.is_some());
let server_hello = Tls13ServerHello::new(Tls13CipherSuite::Aes256GcmSha384);
handshake.process_server_hello(server_hello).unwrap();
assert_eq!(handshake.state, Tls13HandshakeState::ServerHelloReceived);
let cert = Tls13Certificate::new();
assert!(handshake.process_certificate(cert).is_err());
let mut cert2 = Tls13Certificate::new();
cert2.add_certificate(vec![0x30, 0x01, 0x02, 0x03]);
handshake.process_certificate(cert2).unwrap();
assert_eq!(handshake.state, Tls13HandshakeState::CertificateReceived);
handshake.complete_handshake().unwrap();
assert!(handshake.is_connected());
assert_eq!(
handshake.cipher_suite(),
Some(Tls13CipherSuite::Aes256GcmSha384)
);
}
#[test]
fn test_tls13_certificate_wire_format() {
let mut cert = Tls13Certificate::new();
cert.add_certificate(vec![0x30; 100]);
let wire = cert.to_wire();
assert!(wire.len() > 0);
assert_eq!(wire[0], 0x00);
}
#[test]
fn test_crypto_registry_default() {
let reg = CryptoRegistry::default_registry();
assert_eq!(reg.libraries.len(), 8);
}
#[test]
fn test_crypto_registry_compile_all() {
let mut reg = CryptoRegistry::default_registry();
let results = reg.compile_all();
assert_eq!(results.len(), 8);
assert!(results.iter().all(|r| r.success));
}
#[test]
fn test_crypto_registry_run_all_tests() {
let reg = CryptoRegistry::default_registry();
let results = reg.run_all_tests();
assert_eq!(results.len(), 8);
assert!(results.iter().all(|r| r.failed == 0));
}
#[test]
fn test_crypto_registry_total_files() {
let mut reg = CryptoRegistry::default_registry();
reg.compile_all();
assert!(reg.total_files() > 100);
}
#[test]
fn test_crypto_test_case_with_algorithm() {
let test = CryptoTestCase::new("test_aes", true)
.with_algorithm("AES-256-GCM")
.with_error("none");
assert!(test.passed);
assert_eq!(test.algorithm.unwrap(), "AES-256-GCM");
}
}