From 95e4a11aa91d32ce81db39edcace6597c2996015 Mon Sep 17 00:00:00 2001 From: Ernst Rohlicek Date: Tue, 3 May 2016 23:12:45 +0200 Subject: [PATCH 1/2] Change digest implementation from local implementation to rust-crypto. --- Cargo.toml | 7 +- build.rs | 4 +- build.sh | 1 - src/hash.rs | 458 --------------------------------- src/hash.rs.erb | 103 -------- src/ssh.rs | 7 +- src/sshio.rs | 2 +- src/transport/ssh_socket.rs | 4 +- src/transport/ssh_transport.rs | 48 ++-- 9 files changed, 40 insertions(+), 594 deletions(-) delete mode 100644 build.sh delete mode 100644 src/hash.rs delete mode 100644 src/hash.rs.erb diff --git a/Cargo.toml b/Cargo.toml index 6c5b8a5..a67286b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,13 +1,14 @@ [package] name = "ssh" -version = "0.1.0" +version = "0.1.1" authors = ["Jens Nockert "] -build = "build.rs" +#build = "build.rs" # NOTE: unused at the moment [dependencies] num = "*" rand = "0.3" byteorder = "0.3" +rust-crypto = "^0.2" [dev-dependencies] quickcheck = "0.2" @@ -15,4 +16,4 @@ quickcheck_macros = "0.2" [[bin]] name = "ssh" -path = "src/ssh.rs" \ No newline at end of file +path = "src/ssh.rs" diff --git a/build.rs b/build.rs index 3efafdf..47cb46f 100644 --- a/build.rs +++ b/build.rs @@ -1,5 +1,7 @@ +/* NOTE: unused, code snippet may be of use sometime later use std::process::Command; fn main() { Command::new("sh").args(&["build.sh"]).status().unwrap(); -} \ No newline at end of file +} +*/ diff --git a/build.sh b/build.sh deleted file mode 100644 index fa165bc..0000000 --- a/build.sh +++ /dev/null @@ -1 +0,0 @@ -erb -T 1 src/hash.rs.erb > src/hash.rs \ No newline at end of file diff --git a/src/hash.rs b/src/hash.rs deleted file mode 100644 index 46d651b..0000000 --- a/src/hash.rs +++ /dev/null @@ -1,458 +0,0 @@ -extern crate libc; - -use std::default::Default; - -pub trait Hash { - fn update(&mut self, input: &[u8]); - fn digest(&mut self) -> Vec; -} - -#[repr(C)] struct MD5_CTX { content: [u8; 92] } - -impl Default for MD5_CTX { - fn default() -> MD5_CTX { - return MD5_CTX { content: [0; 92] }; - } -} -#[repr(C)] struct SHA_CTX { content: [u8; 96] } - -impl Default for SHA_CTX { - fn default() -> SHA_CTX { - return SHA_CTX { content: [0; 96] }; - } -} -#[repr(C)] struct SHA256_CTX { content: [u8; 112] } - -impl Default for SHA256_CTX { - fn default() -> SHA256_CTX { - return SHA256_CTX { content: [0; 112] }; - } -} -#[repr(C)] struct SHA512_CTX { content: [u8; 216] } - -impl Default for SHA512_CTX { - fn default() -> SHA512_CTX { - return SHA512_CTX { content: [0; 216] }; - } -} - -#[link(name = "crypto")] -extern { - fn MD5_Init(context: *mut MD5_CTX) -> libc::c_int; - fn MD5_Update(context: *mut MD5_CTX, data: *const u8, length: libc::c_ulong) -> libc::c_int; - fn MD5_Final(result: *mut u8, context: *mut MD5_CTX) -> libc::c_int; -} - -/// A MD5 hash. -pub struct MD5 { - context: MD5_CTX -} - -/// A MD5 hash. -impl MD5 { - /// Constructs a new MD5 hash. - pub fn new() -> MD5 { - let mut context: MD5_CTX = Default::default(); - - if unsafe { MD5_Init(&mut context) } != 1 { - panic!("Failed to initialize MD5 state"); - } - - return MD5 { context: context } - } -} - -impl Hash for MD5 { - fn update(&mut self, input: &[u8]) { - let err = unsafe { MD5_Update(&mut self.context, input.as_ptr(), input.len() as u64) }; - - if err != 1 { panic!("Failed to update MD5 state") } - } - - fn digest(&mut self) -> Vec { - let mut result = [0u8; 16]; - - let err = unsafe { MD5_Final((&mut result[..]).as_mut_ptr(), &mut self.context) }; - - if err != 1 { panic!("Failed to finalize MD5 state") } - - return result.to_vec(); - } -} - -#[test] -fn calculates_null_md5_hash() { - let mut hash = MD5::new(); - - let null_hash = &[0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e]; - let digest = hash.digest(); - - for i in 0 .. null_hash.len() { - assert_eq!(digest[i], null_hash[i]); - } -} - -#[test] -fn calculates_foxy_md5_hash() { - let mut hash = MD5::new(); - - hash.update(b"The quick brown fox jumps over the lazy dog"); - - let foxy_hash = &[0x9e, 0x10, 0x7d, 0x9d, 0x37, 0x2b, 0xb6, 0x82, 0x6b, 0xd8, 0x1d, 0x35, 0x42, 0xa4, 0x19, 0xd6]; - let digest = hash.digest(); - - for i in 0 .. foxy_hash.len() { - assert_eq!(digest[i], foxy_hash[i]); - } -} - -#[link(name = "crypto")] -extern { - fn SHA1_Init(context: *mut SHA_CTX) -> libc::c_int; - fn SHA1_Update(context: *mut SHA_CTX, data: *const u8, length: libc::c_ulong) -> libc::c_int; - fn SHA1_Final(result: *mut u8, context: *mut SHA_CTX) -> libc::c_int; -} - -/// A SHA1 hash. -pub struct SHA1 { - context: SHA_CTX -} - -/// A SHA1 hash. -impl SHA1 { - /// Constructs a new SHA1 hash. - pub fn new() -> SHA1 { - let mut context: SHA_CTX = Default::default(); - - if unsafe { SHA1_Init(&mut context) } != 1 { - panic!("Failed to initialize SHA1 state"); - } - - return SHA1 { context: context } - } -} - -impl Hash for SHA1 { - fn update(&mut self, input: &[u8]) { - let err = unsafe { SHA1_Update(&mut self.context, input.as_ptr(), input.len() as u64) }; - - if err != 1 { panic!("Failed to update SHA1 state") } - } - - fn digest(&mut self) -> Vec { - let mut result = [0u8; 20]; - - let err = unsafe { SHA1_Final((&mut result[..]).as_mut_ptr(), &mut self.context) }; - - if err != 1 { panic!("Failed to finalize SHA1 state") } - - return result.to_vec(); - } -} - -#[test] -fn calculates_null_sha1_hash() { - let mut hash = SHA1::new(); - - let null_hash = &[0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09]; - let digest = hash.digest(); - - for i in 0 .. null_hash.len() { - assert_eq!(digest[i], null_hash[i]); - } -} - -#[test] -fn calculates_foxy_sha1_hash() { - let mut hash = SHA1::new(); - - hash.update(b"The quick brown fox jumps over the lazy dog"); - - let foxy_hash = &[0x2f, 0xd4, 0xe1, 0xc6, 0x7a, 0x2d, 0x28, 0xfc, 0xed, 0x84, 0x9e, 0xe1, 0xbb, 0x76, 0xe7, 0x39, 0x1b, 0x93, 0xeb, 0x12]; - let digest = hash.digest(); - - for i in 0 .. foxy_hash.len() { - assert_eq!(digest[i], foxy_hash[i]); - } -} - -#[link(name = "crypto")] -extern { - fn SHA224_Init(context: *mut SHA256_CTX) -> libc::c_int; - fn SHA224_Update(context: *mut SHA256_CTX, data: *const u8, length: libc::c_ulong) -> libc::c_int; - fn SHA224_Final(result: *mut u8, context: *mut SHA256_CTX) -> libc::c_int; -} - -/// A SHA224 hash. -pub struct SHA224 { - context: SHA256_CTX -} - -/// A SHA224 hash. -impl SHA224 { - /// Constructs a new SHA224 hash. - pub fn new() -> SHA224 { - let mut context: SHA256_CTX = Default::default(); - - if unsafe { SHA224_Init(&mut context) } != 1 { - panic!("Failed to initialize SHA224 state"); - } - - return SHA224 { context: context } - } -} - -impl Hash for SHA224 { - fn update(&mut self, input: &[u8]) { - let err = unsafe { SHA224_Update(&mut self.context, input.as_ptr(), input.len() as u64) }; - - if err != 1 { panic!("Failed to update SHA224 state") } - } - - fn digest(&mut self) -> Vec { - let mut result = [0u8; 28]; - - let err = unsafe { SHA224_Final((&mut result[..]).as_mut_ptr(), &mut self.context) }; - - if err != 1 { panic!("Failed to finalize SHA224 state") } - - return result.to_vec(); - } -} - -#[test] -fn calculates_null_sha224_hash() { - let mut hash = SHA224::new(); - - let null_hash = &[0xd1, 0x4a, 0x02, 0x8c, 0x2a, 0x3a, 0x2b, 0xc9, 0x47, 0x61, 0x02, 0xbb, 0x28, 0x82, 0x34, 0xc4, 0x15, 0xa2, 0xb0, 0x1f, 0x82, 0x8e, 0xa6, 0x2a, 0xc5, 0xb3, 0xe4, 0x2f]; - let digest = hash.digest(); - - for i in 0 .. null_hash.len() { - assert_eq!(digest[i], null_hash[i]); - } -} - -#[test] -fn calculates_foxy_sha224_hash() { - let mut hash = SHA224::new(); - - hash.update(b"The quick brown fox jumps over the lazy dog"); - - let foxy_hash = &[0x73, 0x0e, 0x10, 0x9b, 0xd7, 0xa8, 0xa3, 0x2b, 0x1c, 0xb9, 0xd9, 0xa0, 0x9a, 0xa2, 0x32, 0x5d, 0x24, 0x30, 0x58, 0x7d, 0xdb, 0xc0, 0xc3, 0x8b, 0xad, 0x91, 0x15, 0x25]; - let digest = hash.digest(); - - for i in 0 .. foxy_hash.len() { - assert_eq!(digest[i], foxy_hash[i]); - } -} - -#[link(name = "crypto")] -extern { - fn SHA256_Init(context: *mut SHA256_CTX) -> libc::c_int; - fn SHA256_Update(context: *mut SHA256_CTX, data: *const u8, length: libc::c_ulong) -> libc::c_int; - fn SHA256_Final(result: *mut u8, context: *mut SHA256_CTX) -> libc::c_int; -} - -/// A SHA256 hash. -pub struct SHA256 { - context: SHA256_CTX -} - -/// A SHA256 hash. -impl SHA256 { - /// Constructs a new SHA256 hash. - pub fn new() -> SHA256 { - let mut context: SHA256_CTX = Default::default(); - - if unsafe { SHA256_Init(&mut context) } != 1 { - panic!("Failed to initialize SHA256 state"); - } - - return SHA256 { context: context } - } -} - -impl Hash for SHA256 { - fn update(&mut self, input: &[u8]) { - let err = unsafe { SHA256_Update(&mut self.context, input.as_ptr(), input.len() as u64) }; - - if err != 1 { panic!("Failed to update SHA256 state") } - } - - fn digest(&mut self) -> Vec { - let mut result = [0u8; 32]; - - let err = unsafe { SHA256_Final((&mut result[..]).as_mut_ptr(), &mut self.context) }; - - if err != 1 { panic!("Failed to finalize SHA256 state") } - - return result.to_vec(); - } -} - -#[test] -fn calculates_null_sha256_hash() { - let mut hash = SHA256::new(); - - let null_hash = &[0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55]; - let digest = hash.digest(); - - for i in 0 .. null_hash.len() { - assert_eq!(digest[i], null_hash[i]); - } -} - -#[test] -fn calculates_foxy_sha256_hash() { - let mut hash = SHA256::new(); - - hash.update(b"The quick brown fox jumps over the lazy dog"); - - let foxy_hash = &[0xd7, 0xa8, 0xfb, 0xb3, 0x07, 0xd7, 0x80, 0x94, 0x69, 0xca, 0x9a, 0xbc, 0xb0, 0x08, 0x2e, 0x4f, 0x8d, 0x56, 0x51, 0xe4, 0x6d, 0x3c, 0xdb, 0x76, 0x2d, 0x02, 0xd0, 0xbf, 0x37, 0xc9, 0xe5, 0x92]; - let digest = hash.digest(); - - for i in 0 .. foxy_hash.len() { - assert_eq!(digest[i], foxy_hash[i]); - } -} - -#[link(name = "crypto")] -extern { - fn SHA384_Init(context: *mut SHA512_CTX) -> libc::c_int; - fn SHA384_Update(context: *mut SHA512_CTX, data: *const u8, length: libc::c_ulong) -> libc::c_int; - fn SHA384_Final(result: *mut u8, context: *mut SHA512_CTX) -> libc::c_int; -} - -/// A SHA384 hash. -pub struct SHA384 { - context: SHA512_CTX -} - -/// A SHA384 hash. -impl SHA384 { - /// Constructs a new SHA384 hash. - pub fn new() -> SHA384 { - let mut context: SHA512_CTX = Default::default(); - - if unsafe { SHA384_Init(&mut context) } != 1 { - panic!("Failed to initialize SHA384 state"); - } - - return SHA384 { context: context } - } -} - -impl Hash for SHA384 { - fn update(&mut self, input: &[u8]) { - let err = unsafe { SHA384_Update(&mut self.context, input.as_ptr(), input.len() as u64) }; - - if err != 1 { panic!("Failed to update SHA384 state") } - } - - fn digest(&mut self) -> Vec { - let mut result = [0u8; 48]; - - let err = unsafe { SHA384_Final((&mut result[..]).as_mut_ptr(), &mut self.context) }; - - if err != 1 { panic!("Failed to finalize SHA384 state") } - - return result.to_vec(); - } -} - -#[test] -fn calculates_null_sha384_hash() { - let mut hash = SHA384::new(); - - let null_hash = &[0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a, 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda, 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b]; - let digest = hash.digest(); - - for i in 0 .. null_hash.len() { - assert_eq!(digest[i], null_hash[i]); - } -} - -#[test] -fn calculates_foxy_sha384_hash() { - let mut hash = SHA384::new(); - - hash.update(b"The quick brown fox jumps over the lazy dog"); - - let foxy_hash = &[0xca, 0x73, 0x7f, 0x10, 0x14, 0xa4, 0x8f, 0x4c, 0x0b, 0x6d, 0xd4, 0x3c, 0xb1, 0x77, 0xb0, 0xaf, 0xd9, 0xe5, 0x16, 0x93, 0x67, 0x54, 0x4c, 0x49, 0x40, 0x11, 0xe3, 0x31, 0x7d, 0xbf, 0x9a, 0x50, 0x9c, 0xb1, 0xe5, 0xdc, 0x1e, 0x85, 0xa9, 0x41, 0xbb, 0xee, 0x3d, 0x7f, 0x2a, 0xfb, 0xc9, 0xb1]; - let digest = hash.digest(); - - for i in 0 .. foxy_hash.len() { - assert_eq!(digest[i], foxy_hash[i]); - } -} - -#[link(name = "crypto")] -extern { - fn SHA512_Init(context: *mut SHA512_CTX) -> libc::c_int; - fn SHA512_Update(context: *mut SHA512_CTX, data: *const u8, length: libc::c_ulong) -> libc::c_int; - fn SHA512_Final(result: *mut u8, context: *mut SHA512_CTX) -> libc::c_int; -} - -/// A SHA512 hash. -pub struct SHA512 { - context: SHA512_CTX -} - -/// A SHA512 hash. -impl SHA512 { - /// Constructs a new SHA512 hash. - pub fn new() -> SHA512 { - let mut context: SHA512_CTX = Default::default(); - - if unsafe { SHA512_Init(&mut context) } != 1 { - panic!("Failed to initialize SHA512 state"); - } - - return SHA512 { context: context } - } -} - -impl Hash for SHA512 { - fn update(&mut self, input: &[u8]) { - let err = unsafe { SHA512_Update(&mut self.context, input.as_ptr(), input.len() as u64) }; - - if err != 1 { panic!("Failed to update SHA512 state") } - } - - fn digest(&mut self) -> Vec { - let mut result = [0u8; 64]; - - let err = unsafe { SHA512_Final((&mut result[..]).as_mut_ptr(), &mut self.context) }; - - if err != 1 { panic!("Failed to finalize SHA512 state") } - - return result.to_vec(); - } -} - -#[test] -fn calculates_null_sha512_hash() { - let mut hash = SHA512::new(); - - let null_hash = &[0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd, 0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07, 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc, 0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce, 0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0, 0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f, 0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81, 0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e]; - let digest = hash.digest(); - - for i in 0 .. null_hash.len() { - assert_eq!(digest[i], null_hash[i]); - } -} - -#[test] -fn calculates_foxy_sha512_hash() { - let mut hash = SHA512::new(); - - hash.update(b"The quick brown fox jumps over the lazy dog"); - - let foxy_hash = &[0x07, 0xe5, 0x47, 0xd9, 0x58, 0x6f, 0x6a, 0x73, 0xf7, 0x3f, 0xba, 0xc0, 0x43, 0x5e, 0xd7, 0x69, 0x51, 0x21, 0x8f, 0xb7, 0xd0, 0xc8, 0xd7, 0x88, 0xa3, 0x09, 0xd7, 0x85, 0x43, 0x6b, 0xbb, 0x64, 0x2e, 0x93, 0xa2, 0x52, 0xa9, 0x54, 0xf2, 0x39, 0x12, 0x54, 0x7d, 0x1e, 0x8a, 0x3b, 0x5e, 0xd6, 0xe1, 0xbf, 0xd7, 0x09, 0x78, 0x21, 0x23, 0x3f, 0xa0, 0x53, 0x8f, 0x3d, 0xb8, 0x54, 0xfe, 0xe6]; - let digest = hash.digest(); - - for i in 0 .. foxy_hash.len() { - assert_eq!(digest[i], foxy_hash[i]); - } -} - diff --git a/src/hash.rs.erb b/src/hash.rs.erb deleted file mode 100644 index 082d27e..0000000 --- a/src/hash.rs.erb +++ /dev/null @@ -1,103 +0,0 @@ -extern crate libc; - -use std::default::Default; - -pub trait Hash { - fn update(&mut self, input: &[u8]); - fn digest(&mut self) -> Vec; -} - -<% [ # FIXME: Verify / calculate these sizes on non-OSX. - ['MD5', 92], - ['SHA', 96], - ['SHA256', 112], - ['SHA512', 216] -].each do |context, size| %> -#[repr(C)] struct <%= context %>_CTX { content: [u8; <%= size %>] } - -impl Default for <%= context %>_CTX { - fn default() -> <%= context %>_CTX { - return <%= context%>_CTX { content: [0; <%= size %>] }; - } -} -<% end %> - -<% [ -['MD5', 'MD5', 16, "d41d8cd98f00b204e9800998ecf8427e", "9e107d9d372bb6826bd81d3542a419d6"], -['SHA1', 'SHA', 20, "da39a3ee5e6b4b0d3255bfef95601890afd80709", "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12"], -['SHA224', 'SHA256', 28, "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f", "730e109bd7a8a32b1cb9d9a09aa2325d2430587ddbc0c38bad911525"], -['SHA256', 'SHA256', 32, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592"], -['SHA384', 'SHA512', 48, "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b", "ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c494011e3317dbf9a509cb1e5dc1e85a941bbee3d7f2afbc9b1"], -['SHA512', 'SHA512', 64, "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e", "07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6"] -].each do |name, context, result_size, null_hash, foxy_hash| %> -#[link(name = "crypto")] -extern { - fn <%= name %>_Init(context: *mut <%= context %>_CTX) -> libc::c_int; - fn <%= name %>_Update(context: *mut <%= context %>_CTX, data: *const u8, length: libc::c_ulong) -> libc::c_int; - fn <%= name %>_Final(result: *mut u8, context: *mut <%= context %>_CTX) -> libc::c_int; -} - -/// A <%= name %> hash. -pub struct <%= name %> { - context: <%= context %>_CTX -} - -/// A <%= name %> hash. -impl <%= name %> { - /// Constructs a new <%= name %> hash. - pub fn new() -> <%= name %> { - let mut context: <%= context %>_CTX = Default::default(); - - if unsafe { <%= name %>_Init(&mut context) } != 1 { - panic!("Failed to initialize <%= name %> state"); - } - - return <%= name %> { context: context } - } -} - -impl Hash for <%= name %> { - fn update(&mut self, input: &[u8]) { - let err = unsafe { <%= name %>_Update(&mut self.context, input.as_ptr(), input.len() as u64) }; - - if err != 1 { panic!("Failed to update <%= name %> state") } - } - - fn digest(&mut self) -> Vec { - let mut result = [0u8; <%= result_size %>]; - - let err = unsafe { <%= name %>_Final((&mut result[..]).as_mut_ptr(), &mut self.context) }; - - if err != 1 { panic!("Failed to finalize <%= name %> state") } - - return result.to_vec(); - } -} - -#[test] -fn calculates_null_<%= name.downcase %>_hash() { - let mut hash = <%= name %>::new(); - - let null_hash = &[<%= null_hash.each_char.each_slice(2).map { |x| "0x#{x.join}" }.join(', ') %>]; - let digest = hash.digest(); - - for i in 0 .. null_hash.len() { - assert_eq!(digest[i], null_hash[i]); - } -} - -#[test] -fn calculates_foxy_<%= name.downcase %>_hash() { - let mut hash = <%= name %>::new(); - - hash.update(b"The quick brown fox jumps over the lazy dog"); - - let foxy_hash = &[<%= foxy_hash.each_char.each_slice(2).map { |x| "0x#{x.join}" }.join(', ') %>]; - let digest = hash.digest(); - - for i in 0 .. foxy_hash.len() { - assert_eq!(digest[i], foxy_hash[i]); - } -} - -<% end %> diff --git a/src/ssh.rs b/src/ssh.rs index 5f65818..2087f1f 100644 --- a/src/ssh.rs +++ b/src/ssh.rs @@ -1,5 +1,5 @@ -#![feature(libc)] -#![feature(convert)] +//FIXME unused #![feature(libc)] +//FIXME unused #![feature(convert)] #![cfg_attr(test, feature(plugin))] #![cfg_attr(test, plugin(quickcheck_macros))] @@ -31,8 +31,7 @@ use std::io::{Read, Write}; use std::net::TcpStream; -/// The `hash` module defines ways of hashing and digesting -pub mod hash; +extern crate crypto; /// SSH socket and transport details pub mod transport { diff --git a/src/sshio.rs b/src/sshio.rs index f63caa6..e84c952 100644 --- a/src/sshio.rs +++ b/src/sshio.rs @@ -206,4 +206,4 @@ mod tests { test_roundtrip!(149, vec![0x00, 0x00, 0x00, 0x02, 0x00, 0x95]); test_roundtrip!(36412, vec![0x00, 0x00, 0x00, 0x03, 0x00, 0x8E, 0x3C]); } -} \ No newline at end of file +} diff --git a/src/transport/ssh_socket.rs b/src/transport/ssh_socket.rs index 2ffd184..fb3eaaf 100644 --- a/src/transport/ssh_socket.rs +++ b/src/transport/ssh_socket.rs @@ -106,7 +106,7 @@ mod tests { let mut reader = Cursor::new(server_identifier); let mut writer = Cursor::new(Vec::new()); - + let version_exchange = { let mut socket = Socket::new(&mut reader, &mut writer); @@ -133,7 +133,7 @@ mod tests { let mut reader = Cursor::new(server_identifier); let mut writer = Cursor::new(Vec::new()); - + let mut socket = Socket::new(&mut reader, &mut writer); let _ = socket.version_exchange(); diff --git a/src/transport/ssh_transport.rs b/src/transport/ssh_transport.rs index c5115db..f56799c 100644 --- a/src/transport/ssh_transport.rs +++ b/src/transport/ssh_transport.rs @@ -14,11 +14,13 @@ use rand::Rng; use packets::SSHPacket; use packets::group_exchange; use packets::key_exchange; -use packets::authentication_request; +//TODO unused import use packets::authentication_request; -use hash::{Hash, SHA256}; +use crypto::digest::Digest; +use crypto::sha2::Sha256; +const SHA256RESULT_SIZE: usize = 512/8; // NOTE see Sha256.output_bits(); -use sshio::{SSHRead, SSHWrite}; +use sshio::{SSHRead, SSHWrite}; // TODO would replacing with rust-crypto buffers make sense? /// Holds socket, session identifier and version-exchange information. pub struct Transport<'a> { @@ -146,27 +148,29 @@ impl<'a> Transport<'a> { println!("Buffer: {:?}", buffer); - let mut hash = SHA256::new(); + let mut hash = Sha256::new(); - hash.update(&buffer[..]); + hash.input(&buffer[..]); - let h = hash.digest(); + //let mut h: [u8; sha256resultSize]; + let mut h: Vec = vec![0; SHA256RESULT_SIZE]; // TODO should probably use fixed-size array here + hash.result(&mut h); let session_identifier = match &self.session_identifier { - &None => h.clone(), - &Some(ref s) => s.clone() + &None => h.clone(), // NOTE unfortunately, array is currently (2016-04) not Clone + &Some(ref s) => s.clone() }; self.session_identifier = Some(session_identifier.clone()); - let iv_c2s = generate_key(&mut SHA256::new(), &k, &h[..], b"A", &session_identifier[..]); - let iv_s2c = generate_key(&mut SHA256::new(), &k, &h[..], b"B", &session_identifier[..]); + let iv_c2s = generate_key(&mut Sha256::new(), &k, &h[..], b"A", &session_identifier[..]); + let iv_s2c = generate_key(&mut Sha256::new(), &k, &h[..], b"B", &session_identifier[..]); - let enc_key_c2s = generate_key(&mut SHA256::new(), &k, &h[..], b"C", &session_identifier[..]); - let enc_key_s2c = generate_key(&mut SHA256::new(), &k, &h[..], b"D", &session_identifier[..]); + let enc_key_c2s = generate_key(&mut Sha256::new(), &k, &h[..], b"C", &session_identifier[..]); + let enc_key_s2c = generate_key(&mut Sha256::new(), &k, &h[..], b"D", &session_identifier[..]); - let mac_key_c2s = generate_key(&mut SHA256::new(), &k, &h[..], b"E", &session_identifier[..]); - let mac_key_s2c = generate_key(&mut SHA256::new(), &k, &h[..], b"F", &session_identifier[..]); + let mac_key_c2s = generate_key(&mut Sha256::new(), &k, &h[..], b"E", &session_identifier[..]); + let mac_key_s2c = generate_key(&mut Sha256::new(), &k, &h[..], b"F", &session_identifier[..]); println!("Session ID: {:?}", h); println!("IV (c2s): {:?}", iv_c2s); @@ -187,7 +191,7 @@ impl<'a> Transport<'a> { let padding_length = self.socket.read_u8().unwrap() as u32; let payload = self.socket.read_n(packet_length - padding_length - 1); - let padding = self.socket.read_n(padding_length); + //TODO unused variable: let padding = self.socket.read_n(padding_length); // let mac = self.read_n(mac_length); // TODO: Check padding, mac @@ -221,16 +225,18 @@ impl<'a> Transport<'a> { } } -fn generate_key(hsh: &mut Hash, k: &BigInt, h: &[u8], c: &[u8], sid: &[u8]) -> Vec { +fn generate_key(hsh: &mut Digest, k: &BigInt, h: &[u8], c: &[u8], sid: &[u8]) -> Vec { let mut w = io::Cursor::new(Vec::new()); w.write_mpint(k); - hsh.update(&w.into_inner()[..]); - hsh.update(h); - hsh.update(c); - hsh.update(sid); + hsh.input(&w.into_inner()[..]); + hsh.input(h); + hsh.input(c); + hsh.input(sid); - return hsh.digest(); + let mut h: Vec = Vec::new(); // TODO initialize with known size of digest + hsh.result(&mut h); + return h } fn mod_exp(base: &BigInt, exponent: &BigInt, modulus: &BigInt) -> BigInt { From 66b7762e35dcf0144e54129087cffde0523e1367 Mon Sep 17 00:00:00 2001 From: Ernst Rohlicek Date: Wed, 4 May 2016 00:42:16 +0200 Subject: [PATCH 2/2] Make server address and port configurable via cmdline argument. --- src/ssh.rs | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/ssh.rs b/src/ssh.rs index 2087f1f..8de05de 100644 --- a/src/ssh.rs +++ b/src/ssh.rs @@ -35,12 +35,12 @@ extern crate crypto; /// SSH socket and transport details pub mod transport { - /// Reads and writes SSH messages - pub mod ssh_socket; - /// The SSH conversation - /// - /// The individual conversation bits go into this module. - pub mod ssh_transport; + /// Reads and writes SSH messages + pub mod ssh_socket; + /// The SSH conversation + /// + /// The individual conversation bits go into this module. + pub mod ssh_transport; } /// SSH I/O @@ -49,13 +49,20 @@ mod sshio; pub mod packets; fn main() { - let mut tcp_socket = TcpStream::connect("127.0.0.1:9001").unwrap(); + // parse program arguments + let args: Vec = std::env::args().collect(); + if args.len() != 2 { + println!("Usage: {} [hostname]:[port]", args[0]); + std::process::exit(128); + } + let address = args[1].as_str(); + let mut tcp_socket = TcpStream::connect(address).unwrap(); //"127.0.0.1:9001").unwrap(); - let reader = &mut tcp_socket.try_clone().unwrap() as &mut Read; - let writer = &mut tcp_socket as &mut Write; + let reader = &mut tcp_socket.try_clone().unwrap() as &mut Read; + let writer = &mut tcp_socket as &mut Write; - let mut socket = transport::ssh_socket::Socket::new(reader, writer); - let mut transport = transport::ssh_transport::Transport::new(&mut socket); + let mut socket = transport::ssh_socket::Socket::new(reader, writer); + let mut transport = transport::ssh_transport::Transport::new(&mut socket); - println!("Packet!: {:?}", transport.read()); + println!("Packet!: {:?}", transport.read()); }