diff --git a/Cargo.lock b/Cargo.lock index 555d059..583bd6f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,6 +10,7 @@ dependencies = [ "image 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "sdl2 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 8df6e13..02e7acc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,16 +19,13 @@ log = "0.3.5" cgmath = "0.7.0" lazy_static = "0.1.15" collision = {git = "https://github.com/csherratt/collision-rs", rev = "f80825e"} +openssl = "0.7.8" # clippy = "*" [dependencies.steven_gl] path = "./gl" version = "0" -[dependencies.steven_openssl] -path = "./openssl" -version = "0" - [dependencies.steven_resources] path = "./resources" version = "0" diff --git a/openssl/Cargo.lock b/openssl/Cargo.lock deleted file mode 100644 index 07af0f6..0000000 --- a/openssl/Cargo.lock +++ /dev/null @@ -1,105 +0,0 @@ -[root] -name = "steven_openssl" -version = "0.0.1" -dependencies = [ - "libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "advapi32-sys" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gdi32-sys" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libc" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "libc" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "libressl-pnacl-sys" -version = "2.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "pnacl-build-helper 1.4.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "openssl-sys" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "gdi32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libressl-pnacl-sys 2.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "user32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pkg-config" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "pnacl-build-helper" -version = "1.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "tempdir 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "advapi32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tempdir" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "user32-sys" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winapi" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - diff --git a/openssl/Cargo.toml b/openssl/Cargo.toml deleted file mode 100644 index 2bad444..0000000 --- a/openssl/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "steven_openssl" -version = "0.0.1" -authors = [ "Thinkofdeath " ] - -[dependencies] -libc = "0.2" -openssl-sys = "0.7.6" diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs deleted file mode 100644 index 31eb26b..0000000 --- a/openssl/src/lib.rs +++ /dev/null @@ -1,207 +0,0 @@ -#![feature(unique)] -#![allow(dead_code)] -extern crate libc; -use std::mem; -use std::ptr; - -#[repr(C)] -#[allow(non_snake_case)] -struct SHA_CTX { - h0: libc::c_uint, - h1: libc::c_uint, - h2: libc::c_uint, - h3: libc::c_uint, - h4: libc::c_uint, - N1: libc::c_uint, - NH: libc::c_uint, - data: [libc::c_uint; 16], - num: libc::c_uint -} - -enum RSA{} - -#[allow(non_camel_case_types)] -enum EVP_CIPHER_CTX{} - -#[allow(non_camel_case_types)] -enum EVP_CIPHER{} - -enum ENGINE{} - -const RSA_PKCS1_PADDING : libc::c_int = 1; - -extern { - fn SHA1_Init(c: *mut SHA_CTX) -> libc::c_int; - fn SHA1_Update(c: *mut SHA_CTX, data: *const u8, len: libc::size_t) -> libc::c_int; - fn SHA1_Final(md: *const u8, c: *mut SHA_CTX) -> libc::c_int; - - fn d2i_RSA_PUBKEY(a: *mut *mut RSA, data: *const *const u8, len: libc::c_int) -> *mut RSA; - fn RSA_free(rsa: *mut RSA); - fn RSA_size(rsa: *mut RSA) -> libc::c_int; - fn RSA_public_encrypt(flen: libc::c_int, from: *const u8, to: *mut u8, rsa: *mut RSA, padding: libc::c_int) -> libc::c_int; - - fn RAND_bytes(buf: *mut u8, len: libc::c_int) -> libc::c_int; - - fn EVP_CIPHER_CTX_init(a: *mut EVP_CIPHER_CTX); - fn EVP_EncryptInit_ex(ctx: *mut EVP_CIPHER_CTX, cipher: *const EVP_CIPHER, engine: *mut ENGINE, key: *const u8, iv: *const u8) -> libc::c_int; - fn EVP_DecryptInit_ex(ctx: *mut EVP_CIPHER_CTX, cipher: *const EVP_CIPHER, engine: *mut ENGINE, key: *const u8, iv: *const u8) -> libc::c_int; - fn EVP_EncryptUpdate(ctx: *mut EVP_CIPHER_CTX, out: *mut u8, outl: *mut libc::c_int, input: *const u8, inl: libc::c_int) -> libc::c_int; - fn EVP_DecryptUpdate(ctx: *mut EVP_CIPHER_CTX, out: *mut u8, outl: *mut libc::c_int, input: *const u8, inl: libc::c_int) -> libc::c_int; - fn EVP_aes_128_cfb8() -> *const EVP_CIPHER; - fn EVP_CIPHER_block_size(cipher: *const EVP_CIPHER) -> libc::c_int; - fn EVP_CIPHER_CTX_free(ctx: *mut EVP_CIPHER_CTX); - fn EVP_CIPHER_CTX_cleanup(ctx: *mut EVP_CIPHER_CTX) -> libc::c_int; - fn EVP_CIPHER_CTX_new() -> *mut EVP_CIPHER_CTX; -} - -pub struct EVPCipher { - internal: ptr::Unique, - - block_size: usize, -} - -impl EVPCipher { - pub fn new(key: &[u8], iv: &[u8], decrypt: bool) -> EVPCipher { - unsafe { - let mut e = EVPCipher { - internal: ptr::Unique::new(EVP_CIPHER_CTX_new()), - block_size: EVP_CIPHER_block_size(EVP_aes_128_cfb8()) as usize, - }; - EVP_CIPHER_CTX_init(e.internal.get_mut()); - if decrypt { - if EVP_DecryptInit_ex(e.internal.get_mut(), EVP_aes_128_cfb8(), ptr::null_mut(), key.as_ptr(), iv.as_ptr()) == 0 { - panic!("Init error"); - } - } else { - if EVP_EncryptInit_ex(e.internal.get_mut(), EVP_aes_128_cfb8(), ptr::null_mut(), key.as_ptr(), iv.as_ptr()) == 0 { - panic!("Init error"); - } - } - e - } - } - - pub fn decrypt(&mut self, data: &[u8]) -> Vec { - unsafe { - let mut out = Vec::with_capacity(data.len()); - let mut out_len: libc::c_int = 0; - if EVP_DecryptUpdate(self.internal.get_mut(), out.as_mut_ptr(), &mut out_len, data.as_ptr(), data.len() as libc::c_int) == 0 { - panic!("Decrypt error") - } - out.set_len(out_len as usize); - out - } - } - - pub fn encrypt(&mut self, data: &[u8]) -> Vec { - unsafe { - let mut out = Vec::with_capacity(data.len()); - let mut out_len: libc::c_int = 0; - if EVP_EncryptUpdate(self.internal.get_mut(), out.as_mut_ptr(), &mut out_len, data.as_ptr(), data.len() as libc::c_int) == 0 { - panic!("Encrypt error") - } - out.set_len(out_len as usize); - out - } - } -} - - -impl Drop for EVPCipher { - fn drop(&mut self) { - unsafe { - EVP_CIPHER_CTX_cleanup(self.internal.get_mut()); - EVP_CIPHER_CTX_free(self.internal.get_mut()); - } - } -} - -pub fn gen_random(len: usize) -> Vec { - unsafe { - let mut data = Vec::with_capacity(len); - data.set_len(len); - RAND_bytes(data.as_mut_ptr(), len as libc::c_int); - data - } -} - - -pub struct PublicKey { - rsa: *mut RSA -} - -impl PublicKey { - pub fn new(data: &[u8]) -> PublicKey { - unsafe { - let cert = d2i_RSA_PUBKEY(ptr::null_mut(), &data.as_ptr(), data.len() as libc::c_int); - if cert.is_null() { - panic!("Error"); - } - PublicKey { rsa: cert } - } - } - - pub fn encrypt(&mut self, data: &Vec) -> Vec { - unsafe { - let size = RSA_size(self.rsa) as usize; - let mut out = Vec::with_capacity(size); - out.set_len(size); - RSA_public_encrypt(data.len() as libc::c_int, data.as_ptr(), out.as_mut_ptr(), self.rsa, RSA_PKCS1_PADDING); - out - } - } -} - -impl Drop for PublicKey { - fn drop(&mut self) { - unsafe { - RSA_free(self.rsa); - } - } -} - -pub struct SHA1 { - internal: SHA_CTX, -} - -impl SHA1 { - pub fn new() -> SHA1 { - unsafe { - let mut s : SHA1 = mem::uninitialized(); - if SHA1_Init(&mut s.internal) == 0 { - panic!("error init sha1"); - } - s - } - } - - pub fn update(&mut self, data: &[u8]) { - unsafe { - if SHA1_Update(&mut self.internal, data.as_ptr(), data.len() as libc::size_t) == 0 { - panic!("sha1 error"); - } - } - } - - pub fn bytes(mut self) -> Vec { - unsafe { - let mut dst = Vec::with_capacity(20); - dst.set_len(20); - if SHA1_Final(dst.as_mut_ptr(), &mut self.internal) == 0 { - panic!("sha1 error"); - } - dst - } - } -} - -#[cfg(test)] -mod test { - use super::{SHA1}; - #[test] - fn test_sha1() { - let mut sha1 = SHA1::new(); - sha1.update(b"Hello world"); - assert!(sha1.bytes().iter().map(|b| format!("{:02X}", b)).collect::>().connect("") == "7B502C3A1F48C8609AE212CDFB639DEE39673F5E"); - } -} diff --git a/src/main.rs b/src/main.rs index 4427fc5..59f824e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,7 +21,7 @@ extern crate image; extern crate time; extern crate byteorder; extern crate serde_json; -extern crate steven_openssl as openssl; +extern crate openssl; extern crate hyper; extern crate flate2; extern crate rand; diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs index 330b9ae..f05fe35 100644 --- a/src/protocol/mod.rs +++ b/src/protocol/mod.rs @@ -14,7 +14,7 @@ #![allow(dead_code)] -use openssl; +use openssl::crypto::symm; use serde_json; use hyper; @@ -720,13 +720,16 @@ pub struct Conn { direction: Direction, pub state: State, - cipher: Option, + cipher: Option, compression_threshold: i32, compression_read: Option>>>, compression_write: Option>>>, } +// Needed because symm::Crypter isn't send +unsafe impl Send for Conn {} + impl Conn { pub fn new(target: &str) -> Result { // TODO SRV record support @@ -832,7 +835,9 @@ impl Conn { } pub fn enable_encyption(&mut self, key: &[u8], decrypt: bool) { - self.cipher = Option::Some(openssl::EVPCipher::new(key, key, decrypt)); + let cipher = symm::Crypter::new(symm::Type::AES_128_CFB8); + cipher.init(if decrypt { symm::Mode::Decrypt } else { symm::Mode::Encrypt }, key, key); + self.cipher = Option::Some(cipher); } pub fn set_compresssion(&mut self, threshold: i32) { @@ -940,7 +945,7 @@ impl Read for Conn { Option::None => self.stream.read(buf), Option::Some(cipher) => { let ret = try!(self.stream.read(buf)); - let data = cipher.decrypt(&buf[..ret]); + let data = cipher.update(&buf[..ret]); for i in 0..ret { buf[i] = data[i]; } @@ -955,7 +960,7 @@ impl Write for Conn { match self.cipher.as_mut() { Option::None => self.stream.write(buf), Option::Some(cipher) => { - let data = cipher.encrypt(buf); + let data = cipher.update(buf); try!(self.stream.write_all(&data[..])); Ok(buf.len()) } diff --git a/src/protocol/mojang.rs b/src/protocol/mojang.rs index 45997f5..ee081e8 100644 --- a/src/protocol/mojang.rs +++ b/src/protocol/mojang.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use openssl; +use openssl::crypto::hash; use serde_json; use serde_json::builder::ObjectBuilder; use hyper; @@ -101,11 +101,12 @@ impl Profile { } pub fn join_server(&self, server_id: &str, shared_key: &[u8], public_key: &[u8]) -> Result<(), super::Error> { - let mut sha1 = openssl::SHA1::new(); - sha1.update(server_id.as_bytes()); - sha1.update(shared_key); - sha1.update(public_key); - let mut hash = sha1.bytes(); + use std::io::Write; + let mut sha1 = hash::Hasher::new(hash::Type::SHA1); + sha1.write_all(server_id.as_bytes()).unwrap(); + sha1.write_all(shared_key).unwrap(); + sha1.write_all(public_key).unwrap(); + let mut hash = sha1.finish(); // Mojang uses a hex method which allows for // negatives so we have to account for that. diff --git a/src/server/mod.rs b/src/server/mod.rs index 2d5f293..6fd4363 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -23,7 +23,6 @@ use std::collections::HashMap; use std::hash::BuildHasherDefault; use types::hash::FNVHash; use resources; -use openssl; use console; use render; use auth; @@ -99,6 +98,8 @@ macro_rules! handle_packet { impl Server { pub fn connect(resources: Arc>, console: Arc>, address: &str) -> Result { + use openssl::crypto::pkey; + use openssl::crypto::rand::rand_bytes; let mut conn = try!(protocol::Conn::new(address)); let profile = { @@ -148,11 +149,12 @@ impl Server { }; } - let mut key = openssl::PublicKey::new(&packet.public_key.data); - let shared = openssl::gen_random(16); + let mut key = pkey::PKey::new(); + key.load_pub(&packet.public_key.data); + let shared = rand_bytes(16); - let shared_e = key.encrypt(&shared); - let token_e = key.encrypt(&packet.verify_token.data); + let shared_e = key.public_encrypt_with_padding(&shared, pkey::EncryptionPadding::PKCS1v15); + let token_e = key.public_encrypt_with_padding(&packet.verify_token.data, pkey::EncryptionPadding::PKCS1v15); try!(profile.join_server(&packet.server_id, &shared, &packet.public_key.data));