diff options
| author | Linus Färnstrand <faern@faern.net> | 2022-08-30 10:46:10 +0200 |
|---|---|---|
| committer | Linus Färnstrand <linus@mullvad.net> | 2022-09-07 09:34:13 +0200 |
| commit | d6ec6a76c4e8f03c2e98e6c8e8db68730bd0f3eb (patch) | |
| tree | f116205630cfd22600c172a926d233f4c02b5752 | |
| parent | 98e1e43eb80325839298ccae27aa08c36bc285c4 (diff) | |
| download | mullvadvpn-d6ec6a76c4e8f03c2e98e6c8e8db68730bd0f3eb.tar.xz mullvadvpn-d6ec6a76c4e8f03c2e98e6c8e8db68730bd0f3eb.zip | |
Upgrade the classic-mceliece-rust library
| -rw-r--r-- | Cargo.lock | 6 | ||||
| -rw-r--r-- | talpid-tunnel-config-client/Cargo.toml | 7 | ||||
| -rw-r--r-- | talpid-tunnel-config-client/src/kem.rs | 60 | ||||
| -rw-r--r-- | talpid-tunnel-config-client/src/lib.rs | 14 |
4 files changed, 19 insertions, 68 deletions
diff --git a/Cargo.lock b/Cargo.lock index 67f5fb0a34..3ede836099 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -344,11 +344,13 @@ dependencies = [ [[package]] name = "classic-mceliece-rust" -version = "1.0.1" -source = "git+https://github.com/mullvad/classic-mceliece-rust?rev=5130d9e3bfbf54735177e15636a643366c250b78#5130d9e3bfbf54735177e15636a643366c250b78" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0022efd83c4782eb5db72d205319ecf145ae0c8f5f55987538510f0c24b39991" dependencies = [ "rand 0.8.5", "sha3", + "zeroize", ] [[package]] diff --git a/talpid-tunnel-config-client/Cargo.toml b/talpid-tunnel-config-client/Cargo.toml index 18ce417468..1d41868ca5 100644 --- a/talpid-tunnel-config-client/Cargo.toml +++ b/talpid-tunnel-config-client/Cargo.toml @@ -16,12 +16,7 @@ prost = "0.8" prost-types = "0.9" tower = "0.4" tokio = "1" - -[dependencies.classic-mceliece-rust] -git = "https://github.com/mullvad/classic-mceliece-rust" -rev = "5130d9e3bfbf54735177e15636a643366c250b78" -version = "1.0.1" -features = ["mceliece8192128f"] +classic-mceliece-rust = { version = "2.0.0", features = ["mceliece8192128f"] } [dev-dependencies] tokio = { version = "1", features = ["rt-multi-thread"] } diff --git a/talpid-tunnel-config-client/src/kem.rs b/talpid-tunnel-config-client/src/kem.rs index 35679ccddf..778c66a0aa 100644 --- a/talpid-tunnel-config-client/src/kem.rs +++ b/talpid-tunnel-config-client/src/kem.rs @@ -1,67 +1,25 @@ -use std::fmt; - -use super::Error; - -use classic_mceliece_rust::{ - crypto_kem_dec, crypto_kem_keypair, CRYPTO_BYTES, CRYPTO_PUBLICKEYBYTES, CRYPTO_SECRETKEYBYTES, -}; +use classic_mceliece_rust::keypair_boxed; use talpid_types::net::wireguard::PresharedKey; -const STACK_SIZE: usize = 8 * 1024 * 1024; -pub use classic_mceliece_rust::CRYPTO_CIPHERTEXTBYTES; - -#[derive(Debug)] -pub struct PublicKey(Box<[u8; CRYPTO_PUBLICKEYBYTES]>); +const STACK_SIZE: usize = 2 * 1024 * 1024; -impl PublicKey { - pub fn into_vec(self) -> Vec<u8> { - (self.0 as Box<[u8]>).into_vec() - } -} - -pub struct SecretKey(Box<[u8; CRYPTO_SECRETKEYBYTES]>); +pub use classic_mceliece_rust::{Ciphertext, PublicKey, SecretKey, CRYPTO_CIPHERTEXTBYTES}; -impl fmt::Debug for SecretKey { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("SecretKey").finish() - } -} - -pub async fn generate_keys() -> Result<(PublicKey, SecretKey), Error> { +pub async fn generate_keys() -> (PublicKey<'static>, SecretKey<'static>) { let (tx, rx) = tokio::sync::oneshot::channel(); - let gen_key = move || { - let mut rng = rand::thread_rng(); - let mut pubkey = Box::new([0u8; CRYPTO_PUBLICKEYBYTES]); - let mut secret = Box::new([0u8; CRYPTO_SECRETKEYBYTES]); - crypto_kem_keypair(&mut pubkey, &mut secret, &mut rng).map_err(|error| { - log::error!("KEM keypair generation failed: {error}"); - Error::KeyGenerationFailed - })?; - - Ok((PublicKey(pubkey), SecretKey(secret))) - }; - std::thread::Builder::new() .stack_size(STACK_SIZE) .spawn(move || { - let _ = tx.send(gen_key()); + let keypair = keypair_boxed(&mut rand::thread_rng()); + let _ = tx.send(keypair); }) .unwrap(); rx.await.unwrap() } -pub fn decapsulate( - secret: &SecretKey, - ciphertext: &[u8; CRYPTO_CIPHERTEXTBYTES], -) -> Result<PresharedKey, Error> { - let mut psk = [0u8; CRYPTO_BYTES]; - - crypto_kem_dec(&mut psk, ciphertext, &secret.0).map_err(|error| { - log::error!("KEM decapsulation failed: {error}"); - Error::DecapsulationError - })?; - - Ok(PresharedKey::from(psk)) +pub fn decapsulate(secret: &SecretKey, ciphertext: &Ciphertext) -> PresharedKey { + let shared_secret = classic_mceliece_rust::decapsulate_boxed(ciphertext, secret); + PresharedKey::from(*shared_secret.as_array()) } diff --git a/talpid-tunnel-config-client/src/lib.rs b/talpid-tunnel-config-client/src/lib.rs index b1356aba1b..4dce3edf67 100644 --- a/talpid-tunnel-config-client/src/lib.rs +++ b/talpid-tunnel-config-client/src/lib.rs @@ -13,8 +13,6 @@ mod proto { pub enum Error { GrpcConnectError(tonic::transport::Error), GrpcError(tonic::Status), - KeyGenerationFailed, - DecapsulationError, InvalidCiphertext, } @@ -24,8 +22,6 @@ impl std::fmt::Display for Error { match self { GrpcConnectError(_) => "Failed to connect to config service".fmt(f), GrpcError(status) => write!(f, "RPC failed: {}", status), - KeyGenerationFailed => "Failed to generate KEM key pair".fmt(f), - DecapsulationError => "Failed to decapsulate secret".fmt(f), InvalidCiphertext => "The service returned an invalid ciphertext".fmt(f), } } @@ -56,7 +52,7 @@ pub async fn push_pq_key( wg_pubkey: PublicKey, ) -> Result<(PrivateKey, PresharedKey), Error> { let wg_psk_privkey = PrivateKey::new_from_random(); - let (kem_pubkey, kem_secret) = kem::generate_keys().await?; + let (kem_pubkey, kem_secret) = kem::generate_keys().await; let mut client = new_client(service_address).await?; let response = client @@ -65,19 +61,19 @@ pub async fn push_pq_key( wg_psk_pubkey: wg_psk_privkey.public_key().as_bytes().to_vec(), kem_pubkey: Some(proto::KemPubkeyExperimentalV0 { algorithm_name: ALGORITHM_NAME.to_string(), - key_data: kem_pubkey.into_vec(), + key_data: kem_pubkey.as_array().to_vec(), }), }) .await .map_err(Error::GrpcError)?; - let ciphertext: [u8; kem::CRYPTO_CIPHERTEXTBYTES] = response + let ciphertext_array: [u8; kem::CRYPTO_CIPHERTEXTBYTES] = response .into_inner() .ciphertext .try_into() .map_err(|_| Error::InvalidCiphertext)?; - - Ok((wg_psk_privkey, kem::decapsulate(&kem_secret, &ciphertext)?)) + let ciphertext = kem::Ciphertext::from(ciphertext_array); + Ok((wg_psk_privkey, kem::decapsulate(&kem_secret, &ciphertext))) } async fn new_client(addr: IpAddr) -> Result<RelayConfigService, Error> { |
