From d3a63792dfc1ad3831be7a075fefbd9f6a363994 Mon Sep 17 00:00:00 2001 From: Palmer Cox
Date: Sat, 27 Jul 2013 13:41:50 -0400 Subject: [PATCH 1/9] Sha2: Remove unecessary integer type specifications. --- src/libextra/crypto/sha2.rs | 72 ++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/src/libextra/crypto/sha2.rs b/src/libextra/crypto/sha2.rs index f21722e8d7af0..9ded8dbaf57b6 100644 --- a/src/libextra/crypto/sha2.rs +++ b/src/libextra/crypto/sha2.rs @@ -314,26 +314,26 @@ impl Engine512 { // Constants necessary for SHA-2 512 family of digests. static K64: [u64, ..80] = [ - 0x428a2f98d728ae22u64, 0x7137449123ef65cdu64, 0xb5c0fbcfec4d3b2fu64, 0xe9b5dba58189dbbcu64, - 0x3956c25bf348b538u64, 0x59f111f1b605d019u64, 0x923f82a4af194f9bu64, 0xab1c5ed5da6d8118u64, - 0xd807aa98a3030242u64, 0x12835b0145706fbeu64, 0x243185be4ee4b28cu64, 0x550c7dc3d5ffb4e2u64, - 0x72be5d74f27b896fu64, 0x80deb1fe3b1696b1u64, 0x9bdc06a725c71235u64, 0xc19bf174cf692694u64, - 0xe49b69c19ef14ad2u64, 0xefbe4786384f25e3u64, 0x0fc19dc68b8cd5b5u64, 0x240ca1cc77ac9c65u64, - 0x2de92c6f592b0275u64, 0x4a7484aa6ea6e483u64, 0x5cb0a9dcbd41fbd4u64, 0x76f988da831153b5u64, - 0x983e5152ee66dfabu64, 0xa831c66d2db43210u64, 0xb00327c898fb213fu64, 0xbf597fc7beef0ee4u64, - 0xc6e00bf33da88fc2u64, 0xd5a79147930aa725u64, 0x06ca6351e003826fu64, 0x142929670a0e6e70u64, - 0x27b70a8546d22ffcu64, 0x2e1b21385c26c926u64, 0x4d2c6dfc5ac42aedu64, 0x53380d139d95b3dfu64, - 0x650a73548baf63deu64, 0x766a0abb3c77b2a8u64, 0x81c2c92e47edaee6u64, 0x92722c851482353bu64, - 0xa2bfe8a14cf10364u64, 0xa81a664bbc423001u64, 0xc24b8b70d0f89791u64, 0xc76c51a30654be30u64, - 0xd192e819d6ef5218u64, 0xd69906245565a910u64, 0xf40e35855771202au64, 0x106aa07032bbd1b8u64, - 0x19a4c116b8d2d0c8u64, 0x1e376c085141ab53u64, 0x2748774cdf8eeb99u64, 0x34b0bcb5e19b48a8u64, - 0x391c0cb3c5c95a63u64, 0x4ed8aa4ae3418acbu64, 0x5b9cca4f7763e373u64, 0x682e6ff3d6b2b8a3u64, - 0x748f82ee5defb2fcu64, 0x78a5636f43172f60u64, 0x84c87814a1f0ab72u64, 0x8cc702081a6439ecu64, - 0x90befffa23631e28u64, 0xa4506cebde82bde9u64, 0xbef9a3f7b2c67915u64, 0xc67178f2e372532bu64, - 0xca273eceea26619cu64, 0xd186b8c721c0c207u64, 0xeada7dd6cde0eb1eu64, 0xf57d4f7fee6ed178u64, - 0x06f067aa72176fbau64, 0x0a637dc5a2c898a6u64, 0x113f9804bef90daeu64, 0x1b710b35131c471bu64, - 0x28db77f523047d84u64, 0x32caab7b40c72493u64, 0x3c9ebe0a15c9bebcu64, 0x431d67c49c100d4cu64, - 0x4cc5d4becb3e42b6u64, 0x597f299cfc657e2au64, 0x5fcb6fab3ad6faecu64, 0x6c44198c4a475817u64 + 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, + 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, + 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, + 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694, + 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, + 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, + 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, + 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70, + 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, + 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b, + 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, + 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, + 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, + 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, + 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, + 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, + 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, + 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, + 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, + 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817 ]; // A structure that represents that state of a digest computation @@ -578,22 +578,22 @@ impl Engine256 { } static K32: [u32, ..64] = [ - 0x428a2f98u32, 0x71374491u32, 0xb5c0fbcfu32, 0xe9b5dba5u32, - 0x3956c25bu32, 0x59f111f1u32, 0x923f82a4u32, 0xab1c5ed5u32, - 0xd807aa98u32, 0x12835b01u32, 0x243185beu32, 0x550c7dc3u32, - 0x72be5d74u32, 0x80deb1feu32, 0x9bdc06a7u32, 0xc19bf174u32, - 0xe49b69c1u32, 0xefbe4786u32, 0x0fc19dc6u32, 0x240ca1ccu32, - 0x2de92c6fu32, 0x4a7484aau32, 0x5cb0a9dcu32, 0x76f988dau32, - 0x983e5152u32, 0xa831c66du32, 0xb00327c8u32, 0xbf597fc7u32, - 0xc6e00bf3u32, 0xd5a79147u32, 0x06ca6351u32, 0x14292967u32, - 0x27b70a85u32, 0x2e1b2138u32, 0x4d2c6dfcu32, 0x53380d13u32, - 0x650a7354u32, 0x766a0abbu32, 0x81c2c92eu32, 0x92722c85u32, - 0xa2bfe8a1u32, 0xa81a664bu32, 0xc24b8b70u32, 0xc76c51a3u32, - 0xd192e819u32, 0xd6990624u32, 0xf40e3585u32, 0x106aa070u32, - 0x19a4c116u32, 0x1e376c08u32, 0x2748774cu32, 0x34b0bcb5u32, - 0x391c0cb3u32, 0x4ed8aa4au32, 0x5b9cca4fu32, 0x682e6ff3u32, - 0x748f82eeu32, 0x78a5636fu32, 0x84c87814u32, 0x8cc70208u32, - 0x90befffau32, 0xa4506cebu32, 0xbef9a3f7u32, 0xc67178f2u32 + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 ]; struct Sha512 { From 2e95cccbd4fdd13b9609490f53b7d3400c80cd08 Mon Sep 17 00:00:00 2001 From: Palmer Cox
Date: Sat, 27 Jul 2013 13:46:58 -0400 Subject: [PATCH 2/9] Sha2: Rearrage traits / impls / structs. The code was arranged so that the core Sha2 code came first, and then all of the various implementation of Digest followed along later. The problem is that the Sha512 compression function code is far away from the Sha512 Digest implementation, so, if you are trying to read over the code, you need to scroll all around the file for no good reason. The code was rearranged so that all of the Sha512 code is in one place and all of the Sha256 code is in another and so that all impls for a struct are near the definition of that struct. --- src/libextra/crypto/sha2.rs | 505 ++++++++++++++++++------------------ 1 file changed, 257 insertions(+), 248 deletions(-) diff --git a/src/libextra/crypto/sha2.rs b/src/libextra/crypto/sha2.rs index 9ded8dbaf57b6..5d13da67aee06 100644 --- a/src/libextra/crypto/sha2.rs +++ b/src/libextra/crypto/sha2.rs @@ -13,6 +13,7 @@ use std::uint; use digest::Digest; + // BitCounter is a specialized structure intended simply for counting the // number of bits that have been processed by the SHA-2 512 family of functions. // It does very little overflow checking since such checking is not necessary @@ -46,6 +47,7 @@ impl BitCounter { } } + // A structure that represents that state of a digest computation // for the SHA-2 512 family of digest functions struct Engine512 { @@ -336,6 +338,231 @@ static K64: [u64, ..80] = [ 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817 ]; + +struct Sha512 { + priv engine: Engine512 +} + +impl Sha512 { + /** + * Construct an new instance of a SHA-512 digest. + */ + pub fn new() -> Sha512 { + Sha512 { + engine: Engine512 { + input_buffer: [0u8, ..8], + input_buffer_idx: 0, + bit_counter: BitCounter { high_bit_count: 0, low_byte_count: 0 }, + H0: 0x6a09e667f3bcc908u64, + H1: 0xbb67ae8584caa73bu64, + H2: 0x3c6ef372fe94f82bu64, + H3: 0xa54ff53a5f1d36f1u64, + H4: 0x510e527fade682d1u64, + H5: 0x9b05688c2b3e6c1fu64, + H6: 0x1f83d9abfb41bd6bu64, + H7: 0x5be0cd19137e2179u64, + W: [0u64, ..80], + W_idx: 0, + finished: false, + } + } + } +} + +impl Digest for Sha512 { + fn input(&mut self, d: &[u8]) { + self.engine.input_vec(d); + } + + fn result(&mut self, out: &mut [u8]) { + self.engine.result_512(out) + } + + fn reset(&mut self) { + self.engine.reset(); + + self.engine.H0 = 0x6a09e667f3bcc908u64; + self.engine.H1 = 0xbb67ae8584caa73bu64; + self.engine.H2 = 0x3c6ef372fe94f82bu64; + self.engine.H3 = 0xa54ff53a5f1d36f1u64; + self.engine.H4 = 0x510e527fade682d1u64; + self.engine.H5 = 0x9b05688c2b3e6c1fu64; + self.engine.H6 = 0x1f83d9abfb41bd6bu64; + self.engine.H7 = 0x5be0cd19137e2179u64; + } + + fn output_bits(&self) -> uint { 512 } +} + + +struct Sha384 { + priv engine: Engine512 +} + +impl Sha384 { + /** + * Construct an new instance of a SHA-384 digest. + */ + pub fn new() -> Sha384 { + Sha384 { + engine: Engine512 { + input_buffer: [0u8, ..8], + input_buffer_idx: 0, + bit_counter: BitCounter { high_bit_count: 0, low_byte_count: 0 }, + H0: 0xcbbb9d5dc1059ed8u64, + H1: 0x629a292a367cd507u64, + H2: 0x9159015a3070dd17u64, + H3: 0x152fecd8f70e5939u64, + H4: 0x67332667ffc00b31u64, + H5: 0x8eb44a8768581511u64, + H6: 0xdb0c2e0d64f98fa7u64, + H7: 0x47b5481dbefa4fa4u64, + W: [0u64, ..80], + W_idx: 0, + finished: false, + } + } + } +} + +impl Digest for Sha384 { + fn input(&mut self, d: &[u8]) { + self.engine.input_vec(d); + } + + fn result(&mut self, out: &mut [u8]) { + self.engine.result_384(out) + } + + fn reset(&mut self) { + self.engine.reset(); + + self.engine.H0 = 0xcbbb9d5dc1059ed8u64; + self.engine.H1 = 0x629a292a367cd507u64; + self.engine.H2 = 0x9159015a3070dd17u64; + self.engine.H3 = 0x152fecd8f70e5939u64; + self.engine.H4 = 0x67332667ffc00b31u64; + self.engine.H5 = 0x8eb44a8768581511u64; + self.engine.H6 = 0xdb0c2e0d64f98fa7u64; + self.engine.H7 = 0x47b5481dbefa4fa4u64; + } + + fn output_bits(&self) -> uint { 384 } +} + + +struct Sha512Trunc256 { + priv engine: Engine512 +} + +impl Sha512Trunc256 { + /** + * Construct an new instance of a SHA-512/256 digest. + */ + pub fn new() -> Sha512Trunc256 { + Sha512Trunc256 { + engine: Engine512 { + input_buffer: [0u8, ..8], + input_buffer_idx: 0, + bit_counter: BitCounter { high_bit_count: 0, low_byte_count: 0 }, + H0: 0x22312194fc2bf72cu64, + H1: 0x9f555fa3c84c64c2u64, + H2: 0x2393b86b6f53b151u64, + H3: 0x963877195940eabdu64, + H4: 0x96283ee2a88effe3u64, + H5: 0xbe5e1e2553863992u64, + H6: 0x2b0199fc2c85b8aau64, + H7: 0x0eb72ddc81c52ca2u64, + W: [0u64, ..80], + W_idx: 0, + finished: false, + } + } + } +} + +impl Digest for Sha512Trunc256 { + fn input(&mut self, d: &[u8]) { + self.engine.input_vec(d); + } + + fn result(&mut self, out: &mut [u8]) { + self.engine.result_256(out) + } + + fn reset(&mut self) { + self.engine.reset(); + + self.engine.H0 = 0x22312194fc2bf72cu64; + self.engine.H1 = 0x9f555fa3c84c64c2u64; + self.engine.H2 = 0x2393b86b6f53b151u64; + self.engine.H3 = 0x963877195940eabdu64; + self.engine.H4 = 0x96283ee2a88effe3u64; + self.engine.H5 = 0xbe5e1e2553863992u64; + self.engine.H6 = 0x2b0199fc2c85b8aau64; + self.engine.H7 = 0x0eb72ddc81c52ca2u64; + } + + fn output_bits(&self) -> uint { 256 } +} + + +struct Sha512Trunc224 { + priv engine: Engine512 +} + +impl Sha512Trunc224 { + /** + * Construct an new instance of a SHA-512/224 digest. + */ + pub fn new() -> Sha512Trunc224 { + Sha512Trunc224 { + engine: Engine512 { + input_buffer: [0u8, ..8], + input_buffer_idx: 0, + bit_counter: BitCounter { high_bit_count: 0, low_byte_count: 0 }, + H0: 0x8c3d37c819544da2u64, + H1: 0x73e1996689dcd4d6u64, + H2: 0x1dfab7ae32ff9c82u64, + H3: 0x679dd514582f9fcfu64, + H4: 0x0f6d2b697bd44da8u64, + H5: 0x77e36f7304c48942u64, + H6: 0x3f9d85a86a1d36c8u64, + H7: 0x1112e6ad91d692a1u64, + W: [0u64, ..80], + W_idx: 0, + finished: false, + } + } + } +} + +impl Digest for Sha512Trunc224 { + fn input(&mut self, d: &[u8]) { + self.engine.input_vec(d); + } + + fn result(&mut self, out: &mut [u8]) { + self.engine.result_224(out) + } + + fn reset(&mut self) { + self.engine.reset(); + + self.engine.H0 = 0x8c3d37c819544da2u64; + self.engine.H1 = 0x73e1996689dcd4d6u64; + self.engine.H2 = 0x1dfab7ae32ff9c82u64; + self.engine.H3 = 0x679dd514582f9fcfu64; + self.engine.H4 = 0x0f6d2b697bd44da8u64; + self.engine.H5 = 0x77e36f7304c48942u64; + self.engine.H6 = 0x3f9d85a86a1d36c8u64; + self.engine.H7 = 0x1112e6ad91d692a1u64; + } + + fn output_bits(&self) -> uint { 224 } +} + + // A structure that represents that state of a digest computation // for the SHA-2 256 family of digest functions struct Engine256 { @@ -596,134 +823,11 @@ static K32: [u32, ..64] = [ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 ]; -struct Sha512 { - priv engine: Engine512 -} - -struct Sha384 { - priv engine: Engine512 -} - -struct Sha512Trunc256 { - priv engine: Engine512 -} - -struct Sha512Trunc224 { - priv engine: Engine512 -} struct Sha256 { priv engine: Engine256 } -struct Sha224 { - priv engine: Engine256 -} - -impl Sha512 { - /** - * Construct an new instance of a SHA-512 digest. - */ - pub fn new() -> Sha512 { - Sha512 { - engine: Engine512 { - input_buffer: [0u8, ..8], - input_buffer_idx: 0, - bit_counter: BitCounter { high_bit_count: 0, low_byte_count: 0 }, - H0: 0x6a09e667f3bcc908u64, - H1: 0xbb67ae8584caa73bu64, - H2: 0x3c6ef372fe94f82bu64, - H3: 0xa54ff53a5f1d36f1u64, - H4: 0x510e527fade682d1u64, - H5: 0x9b05688c2b3e6c1fu64, - H6: 0x1f83d9abfb41bd6bu64, - H7: 0x5be0cd19137e2179u64, - W: [0u64, ..80], - W_idx: 0, - finished: false, - } - } - } -} - -impl Sha384 { - /** - * Construct an new instance of a SHA-384 digest. - */ - pub fn new() -> Sha384 { - Sha384 { - engine: Engine512 { - input_buffer: [0u8, ..8], - input_buffer_idx: 0, - bit_counter: BitCounter { high_bit_count: 0, low_byte_count: 0 }, - H0: 0xcbbb9d5dc1059ed8u64, - H1: 0x629a292a367cd507u64, - H2: 0x9159015a3070dd17u64, - H3: 0x152fecd8f70e5939u64, - H4: 0x67332667ffc00b31u64, - H5: 0x8eb44a8768581511u64, - H6: 0xdb0c2e0d64f98fa7u64, - H7: 0x47b5481dbefa4fa4u64, - W: [0u64, ..80], - W_idx: 0, - finished: false, - } - } - } -} - -impl Sha512Trunc256 { - /** - * Construct an new instance of a SHA-512/256 digest. - */ - pub fn new() -> Sha512Trunc256 { - Sha512Trunc256 { - engine: Engine512 { - input_buffer: [0u8, ..8], - input_buffer_idx: 0, - bit_counter: BitCounter { high_bit_count: 0, low_byte_count: 0 }, - H0: 0x22312194fc2bf72cu64, - H1: 0x9f555fa3c84c64c2u64, - H2: 0x2393b86b6f53b151u64, - H3: 0x963877195940eabdu64, - H4: 0x96283ee2a88effe3u64, - H5: 0xbe5e1e2553863992u64, - H6: 0x2b0199fc2c85b8aau64, - H7: 0x0eb72ddc81c52ca2u64, - W: [0u64, ..80], - W_idx: 0, - finished: false, - } - } - } -} - -impl Sha512Trunc224 { - /** - * Construct an new instance of a SHA-512/224 digest. - */ - pub fn new() -> Sha512Trunc224 { - Sha512Trunc224 { - engine: Engine512 { - input_buffer: [0u8, ..8], - input_buffer_idx: 0, - bit_counter: BitCounter { high_bit_count: 0, low_byte_count: 0 }, - H0: 0x8c3d37c819544da2u64, - H1: 0x73e1996689dcd4d6u64, - H2: 0x1dfab7ae32ff9c82u64, - H3: 0x679dd514582f9fcfu64, - H4: 0x0f6d2b697bd44da8u64, - H5: 0x77e36f7304c48942u64, - H6: 0x3f9d85a86a1d36c8u64, - H7: 0x1112e6ad91d692a1u64, - W: [0u64, ..80], - W_idx: 0, - finished: false, - } - } - } -} - impl Sha256 { /** * Construct an new instance of a SHA-256 digest. @@ -750,6 +854,36 @@ impl Sha256 { } } +impl Digest for Sha256 { + fn input(&mut self, d: &[u8]) { + self.engine.input_vec(d); + } + + fn result(&mut self, out: &mut [u8]) { + self.engine.result_256(out) + } + + fn reset(&mut self) { + self.engine.reset(); + + self.engine.H0 = 0x6a09e667u32; + self.engine.H1 = 0xbb67ae85u32; + self.engine.H2 = 0x3c6ef372u32; + self.engine.H3 = 0xa54ff53au32; + self.engine.H4 = 0x510e527fu32; + self.engine.H5 = 0x9b05688cu32; + self.engine.H6 = 0x1f83d9abu32; + self.engine.H7 = 0x5be0cd19u32; + } + + fn output_bits(&self) -> uint { 256 } +} + + +struct Sha224 { + priv engine: Engine256 +} + impl Sha224 { /** * Construct an new instance of a SHA-224 digest. @@ -776,131 +910,6 @@ impl Sha224 { } } -impl Digest for Sha512 { - fn input(&mut self, d: &[u8]) { - self.engine.input_vec(d); - } - - fn result(&mut self, out: &mut [u8]) { - self.engine.result_512(out) - } - - fn reset(&mut self) { - self.engine.reset(); - - self.engine.H0 = 0x6a09e667f3bcc908u64; - self.engine.H1 = 0xbb67ae8584caa73bu64; - self.engine.H2 = 0x3c6ef372fe94f82bu64; - self.engine.H3 = 0xa54ff53a5f1d36f1u64; - self.engine.H4 = 0x510e527fade682d1u64; - self.engine.H5 = 0x9b05688c2b3e6c1fu64; - self.engine.H6 = 0x1f83d9abfb41bd6bu64; - self.engine.H7 = 0x5be0cd19137e2179u64; - } - - fn output_bits(&self) -> uint { 512 } -} - -impl Digest for Sha384 { - fn input(&mut self, d: &[u8]) { - self.engine.input_vec(d); - } - - fn result(&mut self, out: &mut [u8]) { - self.engine.result_384(out) - } - - fn reset(&mut self) { - self.engine.reset(); - - self.engine.H0 = 0xcbbb9d5dc1059ed8u64; - self.engine.H1 = 0x629a292a367cd507u64; - self.engine.H2 = 0x9159015a3070dd17u64; - self.engine.H3 = 0x152fecd8f70e5939u64; - self.engine.H4 = 0x67332667ffc00b31u64; - self.engine.H5 = 0x8eb44a8768581511u64; - self.engine.H6 = 0xdb0c2e0d64f98fa7u64; - self.engine.H7 = 0x47b5481dbefa4fa4u64; - } - - fn output_bits(&self) -> uint { 384 } -} - -impl Digest for Sha512Trunc256 { - fn input(&mut self, d: &[u8]) { - self.engine.input_vec(d); - } - - fn result(&mut self, out: &mut [u8]) { - self.engine.result_256(out) - } - - fn reset(&mut self) { - self.engine.reset(); - - self.engine.H0 = 0x22312194fc2bf72cu64; - self.engine.H1 = 0x9f555fa3c84c64c2u64; - self.engine.H2 = 0x2393b86b6f53b151u64; - self.engine.H3 = 0x963877195940eabdu64; - self.engine.H4 = 0x96283ee2a88effe3u64; - self.engine.H5 = 0xbe5e1e2553863992u64; - self.engine.H6 = 0x2b0199fc2c85b8aau64; - self.engine.H7 = 0x0eb72ddc81c52ca2u64; - } - - fn output_bits(&self) -> uint { 256 } -} - -impl Digest for Sha512Trunc224 { - fn input(&mut self, d: &[u8]) { - self.engine.input_vec(d); - } - - fn result(&mut self, out: &mut [u8]) { - self.engine.result_224(out) - } - - fn reset(&mut self) { - self.engine.reset(); - - self.engine.H0 = 0x8c3d37c819544da2u64; - self.engine.H1 = 0x73e1996689dcd4d6u64; - self.engine.H2 = 0x1dfab7ae32ff9c82u64; - self.engine.H3 = 0x679dd514582f9fcfu64; - self.engine.H4 = 0x0f6d2b697bd44da8u64; - self.engine.H5 = 0x77e36f7304c48942u64; - self.engine.H6 = 0x3f9d85a86a1d36c8u64; - self.engine.H7 = 0x1112e6ad91d692a1u64; - } - - fn output_bits(&self) -> uint { 224 } -} - -impl Digest for Sha256 { - fn input(&mut self, d: &[u8]) { - self.engine.input_vec(d); - } - - fn result(&mut self, out: &mut [u8]) { - self.engine.result_256(out) - } - - fn reset(&mut self) { - self.engine.reset(); - - self.engine.H0 = 0x6a09e667u32; - self.engine.H1 = 0xbb67ae85u32; - self.engine.H2 = 0x3c6ef372u32; - self.engine.H3 = 0xa54ff53au32; - self.engine.H4 = 0x510e527fu32; - self.engine.H5 = 0x9b05688cu32; - self.engine.H6 = 0x1f83d9abu32; - self.engine.H7 = 0x5be0cd19u32; - } - - fn output_bits(&self) -> uint { 256 } -} - impl Digest for Sha224 { fn input(&mut self, d: &[u8]) { self.engine.input_vec(d); From 9cc757368481c8605be44ac0c9ca5ade8b036f3e Mon Sep 17 00:00:00 2001 From: Palmer Cox
Date: Sat, 27 Jul 2013 13:59:41 -0400 Subject: [PATCH 3/9] Sha2: Remove the result_X() methods; move logic into the Digest impls. The result_X() methods just calculate an output of a fixed size. They don't really have much to do with running the actually hash algorithm until the very last step - the output. It makes much more sense to put all this logic into the Digest impls for each specific variation on the hash function. --- src/libextra/crypto/sha2.rs | 123 +++++++++++++++--------------------- 1 file changed, 50 insertions(+), 73 deletions(-) diff --git a/src/libextra/crypto/sha2.rs b/src/libextra/crypto/sha2.rs index 5d13da67aee06..862bf243bc652 100644 --- a/src/libextra/crypto/sha2.rs +++ b/src/libextra/crypto/sha2.rs @@ -270,48 +270,6 @@ impl Engine512 { self.finished = true; } - - fn result_512(&mut self, out: &mut [u8]) { - self.finish(); - - from_u64(self.H0, out.mut_slice(0, 8)); - from_u64(self.H1, out.mut_slice(8, 16)); - from_u64(self.H2, out.mut_slice(16, 24)); - from_u64(self.H3, out.mut_slice(24, 32)); - from_u64(self.H4, out.mut_slice(32, 40)); - from_u64(self.H5, out.mut_slice(40, 48)); - from_u64(self.H6, out.mut_slice(48, 56)); - from_u64(self.H7, out.mut_slice(56, 64)); - } - - fn result_384(&mut self, out: &mut [u8]) { - self.finish(); - - from_u64(self.H0, out.mut_slice(0, 8)); - from_u64(self.H1, out.mut_slice(8, 16)); - from_u64(self.H2, out.mut_slice(16, 24)); - from_u64(self.H3, out.mut_slice(24, 32)); - from_u64(self.H4, out.mut_slice(32, 40)); - from_u64(self.H5, out.mut_slice(40, 48)); - } - - fn result_256(&mut self, out: &mut [u8]) { - self.finish(); - - from_u64(self.H0, out.mut_slice(0, 8)); - from_u64(self.H1, out.mut_slice(8, 16)); - from_u64(self.H2, out.mut_slice(16, 24)); - from_u64(self.H3, out.mut_slice(24, 32)); - } - - fn result_224(&mut self, out: &mut [u8]) { - self.finish(); - - from_u64(self.H0, out.mut_slice(0, 8)); - from_u64(self.H1, out.mut_slice(8, 16)); - from_u64(self.H2, out.mut_slice(16, 24)); - from_u32((self.H3 >> 32) as u32, out.mut_slice(24, 28)); - } } // Constants necessary for SHA-2 512 family of digests. @@ -375,7 +333,17 @@ impl Digest for Sha512 { } fn result(&mut self, out: &mut [u8]) { - self.engine.result_512(out) + self.engine.finish(); + + from_u64(self.engine.H0, out.mut_slice(0, 8)); + from_u64(self.engine.H1, out.mut_slice(8, 16)); + from_u64(self.engine.H2, out.mut_slice(16, 24)); + from_u64(self.engine.H3, out.mut_slice(24, 32)); + from_u64(self.engine.H4, out.mut_slice(32, 40)); + from_u64(self.engine.H5, out.mut_slice(40, 48)); + from_u64(self.engine.H6, out.mut_slice(48, 56)); + from_u64(self.engine.H7, out.mut_slice(56, 64)); + } fn reset(&mut self) { @@ -431,7 +399,14 @@ impl Digest for Sha384 { } fn result(&mut self, out: &mut [u8]) { - self.engine.result_384(out) + self.engine.finish(); + + from_u64(self.engine.H0, out.mut_slice(0, 8)); + from_u64(self.engine.H1, out.mut_slice(8, 16)); + from_u64(self.engine.H2, out.mut_slice(16, 24)); + from_u64(self.engine.H3, out.mut_slice(24, 32)); + from_u64(self.engine.H4, out.mut_slice(32, 40)); + from_u64(self.engine.H5, out.mut_slice(40, 48)); } fn reset(&mut self) { @@ -487,7 +462,12 @@ impl Digest for Sha512Trunc256 { } fn result(&mut self, out: &mut [u8]) { - self.engine.result_256(out) + self.engine.finish(); + + from_u64(self.engine.H0, out.mut_slice(0, 8)); + from_u64(self.engine.H1, out.mut_slice(8, 16)); + from_u64(self.engine.H2, out.mut_slice(16, 24)); + from_u64(self.engine.H3, out.mut_slice(24, 32)); } fn reset(&mut self) { @@ -543,7 +523,12 @@ impl Digest for Sha512Trunc224 { } fn result(&mut self, out: &mut [u8]) { - self.engine.result_224(out) + self.engine.finish(); + + from_u64(self.engine.H0, out.mut_slice(0, 8)); + from_u64(self.engine.H1, out.mut_slice(8, 16)); + from_u64(self.engine.H2, out.mut_slice(16, 24)); + from_u32((self.engine.H3 >> 32) as u32, out.mut_slice(24, 28)); } fn reset(&mut self) { @@ -777,31 +762,6 @@ impl Engine256 { self.finished = true; } - - fn result_256(&mut self, out: &mut [u8]) { - self.finish(); - - from_u32(self.H0, out.mut_slice(0, 4)); - from_u32(self.H1, out.mut_slice(4, 8)); - from_u32(self.H2, out.mut_slice(8, 12)); - from_u32(self.H3, out.mut_slice(12, 16)); - from_u32(self.H4, out.mut_slice(16, 20)); - from_u32(self.H5, out.mut_slice(20, 24)); - from_u32(self.H6, out.mut_slice(24, 28)); - from_u32(self.H7, out.mut_slice(28, 32)); - } - - fn result_224(&mut self, out: &mut [u8]) { - self.finish(); - - from_u32(self.H0, out.mut_slice(0, 4)); - from_u32(self.H1, out.mut_slice(4, 8)); - from_u32(self.H2, out.mut_slice(8, 12)); - from_u32(self.H3, out.mut_slice(12, 16)); - from_u32(self.H4, out.mut_slice(16, 20)); - from_u32(self.H5, out.mut_slice(20, 24)); - from_u32(self.H6, out.mut_slice(24, 28)); - } } static K32: [u32, ..64] = [ @@ -860,7 +820,16 @@ impl Digest for Sha256 { } fn result(&mut self, out: &mut [u8]) { - self.engine.result_256(out) + self.engine.finish(); + + from_u32(self.engine.H0, out.mut_slice(0, 4)); + from_u32(self.engine.H1, out.mut_slice(4, 8)); + from_u32(self.engine.H2, out.mut_slice(8, 12)); + from_u32(self.engine.H3, out.mut_slice(12, 16)); + from_u32(self.engine.H4, out.mut_slice(16, 20)); + from_u32(self.engine.H5, out.mut_slice(20, 24)); + from_u32(self.engine.H6, out.mut_slice(24, 28)); + from_u32(self.engine.H7, out.mut_slice(28, 32)); } fn reset(&mut self) { @@ -916,7 +885,15 @@ impl Digest for Sha224 { } fn result(&mut self, out: &mut [u8]) { - self.engine.result_224(out) + self.engine.finish(); + + from_u32(self.engine.H0, out.mut_slice(0, 4)); + from_u32(self.engine.H1, out.mut_slice(4, 8)); + from_u32(self.engine.H2, out.mut_slice(8, 12)); + from_u32(self.engine.H3, out.mut_slice(12, 16)); + from_u32(self.engine.H4, out.mut_slice(16, 20)); + from_u32(self.engine.H5, out.mut_slice(20, 24)); + from_u32(self.engine.H6, out.mut_slice(24, 28)); } fn reset(&mut self) { From e771aefd1046795865ea995480fe7b59e9da5047 Mon Sep 17 00:00:00 2001 From: Palmer Cox
Date: Sat, 27 Jul 2013 14:02:18 -0400
Subject: [PATCH 4/9] Sha2: Create cryptoutil.rs and re-write the Sha2 module
to make use of it.
There are 2 main pieces of functionality in cryptoutil.rs:
* A set of unsafe function for efficiently reading and writing u32 and u64
values. All of these functions are fairly easy to audit to confirm that
they do what they are supposed to.
* A FixedBuffer struct. This struct keeps track of input data until there
is enough of it to execute the a function on it which expects a fixed
block of data.
The Sha2 module was rewritten to take advantage of the new functions in
cryptoutil as well as FixedBuffer. The result is that the duplicate code
for maintaining a buffer of input data is removed from the Sha512 and
Sha256 implementation. Additionally, the FixedBuffer code is much more
efficient than the previous code was.
---
src/libextra/crypto/cryptoutil.rs | 243 ++++++++++
src/libextra/crypto/sha2.rs | 756 ++++++++++++------------------
src/libextra/extra.rs | 2 +
3 files changed, 549 insertions(+), 452 deletions(-)
create mode 100644 src/libextra/crypto/cryptoutil.rs
diff --git a/src/libextra/crypto/cryptoutil.rs b/src/libextra/crypto/cryptoutil.rs
new file mode 100644
index 0000000000000..71e27a56083b7
--- /dev/null
+++ b/src/libextra/crypto/cryptoutil.rs
@@ -0,0 +1,243 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0
Date: Sat, 27 Jul 2013 14:03:57 -0400
Subject: [PATCH 5/9] Sha2: Re-write the Sha2 compression functions to improve
performance.
The Sha2 compression functions were re-written to execute the message
scheduling calculations in the same loop as the rest of the compression
function. The compiler is able to generate much better code. Additionally,
innermost part of the compression functions were turned into macros to
reduce code duplicate and to make the functions more concise.
---
src/libextra/crypto/sha2.rs | 189 +++++++++++++++++-------------------
1 file changed, 89 insertions(+), 100 deletions(-)
diff --git a/src/libextra/crypto/sha2.rs b/src/libextra/crypto/sha2.rs
index 0b2a3cb903ea3..1b2fd2e0b1faf 100644
--- a/src/libextra/crypto/sha2.rs
+++ b/src/libextra/crypto/sha2.rs
@@ -15,6 +15,25 @@ use cryptoutil::{write_u64_be, write_u32_be, read_u64v_be, read_u32v_be, FixedBu
use digest::Digest;
+// Sha-512 and Sha-256 use basically the same calculations which are implemented by these macros.
+// Inlining the calculations seems to result in better generated code.
+macro_rules! schedule_round( ($t:expr) => (
+ W[$t] = sigma1(W[$t - 2]) + W[$t - 7] + sigma0(W[$t - 15]) + W[$t - 16];
+ )
+)
+
+macro_rules! sha2_round(
+ ($A:ident, $B:ident, $C:ident, $D:ident,
+ $E:ident, $F:ident, $G:ident, $H:ident, $K:ident, $t:expr) => (
+ {
+ $H += sum1($E) + ch($E, $F, $G) + $K[$t] + W[$t];
+ $D += $H;
+ $H += sum0($A) + maj($A, $B, $C);
+ }
+ )
+)
+
+
// BitCounter is a specialized structure intended simply for counting the
// number of bits that have been processed by the SHA-2 512 family of functions.
// It does very little overflow checking since such checking is not necessary
@@ -119,15 +138,6 @@ impl Engine512State {
((x << 45) | (x >> 19)) ^ ((x << 3) | (x >> 61)) ^ (x >> 6)
}
- let mut W = [0u64, ..80];
-
- read_u64v_be(W.mut_slice(0, 16), data);
-
- for uint::range(16, 80) |t| {
- W[t] = sigma1(W[t - 2]) + W[t - 7] + sigma0(W[t - 15]) +
- W[t - 16];
- }
-
let mut a = self.H0;
let mut b = self.H1;
let mut c = self.H2;
@@ -137,47 +147,41 @@ impl Engine512State {
let mut g = self.H6;
let mut h = self.H7;
- let mut t = 0;
- for uint::range(0, 10) |_| {
- h += sum1(e) + ch(e, f, g) + K64[t] + W[t];
- d += h;
- h += sum0(a) + maj(a, b, c);
- t += 1;
-
- g += sum1(d) + ch(d, e, f) + K64[t] + W[t];
- c += g;
- g += sum0(h) + maj(h, a, b);
- t += 1;
-
- f += sum1(c) + ch(c, d, e) + K64[t] + W[t];
- b += f;
- f += sum0(g) + maj(g, h, a);
- t += 1;
-
- e += sum1(b) + ch(b, c, d) + K64[t] + W[t];
- a += e;
- e += sum0(f) + maj(f, g, h);
- t += 1;
-
- d += sum1(a) + ch(a, b, c) + K64[t] + W[t];
- h += d;
- d += sum0(e) + maj(e, f, g);
- t += 1;
-
- c += sum1(h) + ch(h, a, b) + K64[t] + W[t];
- g += c;
- c += sum0(d) + maj(d, e, f);
- t += 1;
-
- b += sum1(g) + ch(g, h, a) + K64[t] + W[t];
- f += b;
- b += sum0(c) + maj(c, d, e);
- t += 1;
-
- a += sum1(f) + ch(f, g, h) + K64[t] + W[t];
- e += a;
- a += sum0(b) + maj(b, c, d);
- t += 1;
+ let mut W = [0u64, ..80];
+
+ read_u64v_be(W.mut_slice(0, 16), data);
+
+ // Putting the message schedule inside the same loop as the round calculations allows for
+ // the compiler to generate better code.
+ for uint::range_step(0, 64, 8) |t| {
+ schedule_round!(t + 16);
+ schedule_round!(t + 17);
+ schedule_round!(t + 18);
+ schedule_round!(t + 19);
+ schedule_round!(t + 20);
+ schedule_round!(t + 21);
+ schedule_round!(t + 22);
+ schedule_round!(t + 23);
+
+ sha2_round!(a, b, c, d, e, f, g, h, K64, t);
+ sha2_round!(h, a, b, c, d, e, f, g, K64, t + 1);
+ sha2_round!(g, h, a, b, c, d, e, f, K64, t + 2);
+ sha2_round!(f, g, h, a, b, c, d, e, K64, t + 3);
+ sha2_round!(e, f, g, h, a, b, c, d, K64, t + 4);
+ sha2_round!(d, e, f, g, h, a, b, c, K64, t + 5);
+ sha2_round!(c, d, e, f, g, h, a, b, K64, t + 6);
+ sha2_round!(b, c, d, e, f, g, h, a, K64, t + 7);
+ }
+
+ for uint::range_step(64, 80, 8) |t| {
+ sha2_round!(a, b, c, d, e, f, g, h, K64, t);
+ sha2_round!(h, a, b, c, d, e, f, g, K64, t + 1);
+ sha2_round!(g, h, a, b, c, d, e, f, K64, t + 2);
+ sha2_round!(f, g, h, a, b, c, d, e, K64, t + 3);
+ sha2_round!(e, f, g, h, a, b, c, d, K64, t + 4);
+ sha2_round!(d, e, f, g, h, a, b, c, K64, t + 5);
+ sha2_round!(c, d, e, f, g, h, a, b, K64, t + 6);
+ sha2_round!(b, c, d, e, f, g, h, a, K64, t + 7);
}
self.H0 += a;
@@ -524,15 +528,6 @@ impl Engine256State {
((x >> 17) | (x << 15)) ^ ((x >> 19) | (x << 13)) ^ (x >> 10)
}
- let mut W = [0u32, ..80];
-
- read_u32v_be(W.mut_slice(0, 16), data);
-
- for uint::range(16, 64) |t| {
- W[t] = sigma1(W[t - 2]) + W[t - 7] + sigma0(W[t - 15]) +
- W[t - 16];
- }
-
let mut a = self.H0;
let mut b = self.H1;
let mut c = self.H2;
@@ -542,47 +537,41 @@ impl Engine256State {
let mut g = self.H6;
let mut h = self.H7;
- let mut t = 0;
- for uint::range(0, 8) |_| {
- h += sum1(e) + ch(e, f, g) + K32[t] + W[t];
- d += h;
- h += sum0(a) + maj(a, b, c);
- t += 1;
-
- g += sum1(d) + ch(d, e, f) + K32[t] + W[t];
- c += g;
- g += sum0(h) + maj(h, a, b);
- t += 1;
-
- f += sum1(c) + ch(c, d, e) + K32[t] + W[t];
- b += f;
- f += sum0(g) + maj(g, h, a);
- t += 1;
-
- e += sum1(b) + ch(b, c, d) + K32[t] + W[t];
- a += e;
- e += sum0(f) + maj(f, g, h);
- t += 1;
-
- d += sum1(a) + ch(a, b, c) + K32[t] + W[t];
- h += d;
- d += sum0(e) + maj(e, f, g);
- t += 1;
-
- c += sum1(h) + ch(h, a, b) + K32[t] + W[t];
- g += c;
- c += sum0(d) + maj(d, e, f);
- t += 1;
-
- b += sum1(g) + ch(g, h, a) + K32[t] + W[t];
- f += b;
- b += sum0(c) + maj(c, d, e);
- t += 1;
-
- a += sum1(f) + ch(f, g, h) + K32[t] + W[t];
- e += a;
- a += sum0(b) + maj(b, c, d);
- t += 1;
+ let mut W = [0u32, ..64];
+
+ read_u32v_be(W.mut_slice(0, 16), data);
+
+ // Putting the message schedule inside the same loop as the round calculations allows for
+ // the compiler to generate better code.
+ for uint::range_step(0, 48, 8) |t| {
+ schedule_round!(t + 16);
+ schedule_round!(t + 17);
+ schedule_round!(t + 18);
+ schedule_round!(t + 19);
+ schedule_round!(t + 20);
+ schedule_round!(t + 21);
+ schedule_round!(t + 22);
+ schedule_round!(t + 23);
+
+ sha2_round!(a, b, c, d, e, f, g, h, K32, t);
+ sha2_round!(h, a, b, c, d, e, f, g, K32, t + 1);
+ sha2_round!(g, h, a, b, c, d, e, f, K32, t + 2);
+ sha2_round!(f, g, h, a, b, c, d, e, K32, t + 3);
+ sha2_round!(e, f, g, h, a, b, c, d, K32, t + 4);
+ sha2_round!(d, e, f, g, h, a, b, c, K32, t + 5);
+ sha2_round!(c, d, e, f, g, h, a, b, K32, t + 6);
+ sha2_round!(b, c, d, e, f, g, h, a, K32, t + 7);
+ }
+
+ for uint::range_step(48, 64, 8) |t| {
+ sha2_round!(a, b, c, d, e, f, g, h, K32, t);
+ sha2_round!(h, a, b, c, d, e, f, g, K32, t + 1);
+ sha2_round!(g, h, a, b, c, d, e, f, K32, t + 2);
+ sha2_round!(f, g, h, a, b, c, d, e, K32, t + 3);
+ sha2_round!(e, f, g, h, a, b, c, d, K32, t + 4);
+ sha2_round!(d, e, f, g, h, a, b, c, K32, t + 5);
+ sha2_round!(c, d, e, f, g, h, a, b, K32, t + 6);
+ sha2_round!(b, c, d, e, f, g, h, a, K32, t + 7);
}
self.H0 += a;
From 3714e3ae1cfb466ee9552e2069e95fe9a73915c3 Mon Sep 17 00:00:00 2001
From: Palmer Cox
Date: Sat, 27 Jul 2013 15:12:49 -0400
Subject: [PATCH 6/9] Crypto: Remove DigestUtil and convert to default methods
on the Digest trait.
---
src/libextra/crypto/digest.rs | 46 +++++++++++++++--------------------
src/libextra/crypto/sha1.rs | 2 +-
src/libextra/crypto/sha2.rs | 2 +-
src/libextra/workcache.rs | 3 +--
4 files changed, 23 insertions(+), 30 deletions(-)
diff --git a/src/libextra/crypto/digest.rs b/src/libextra/crypto/digest.rs
index 26e8b80d8e3c2..8e6b11c8ee9b3 100644
--- a/src/libextra/crypto/digest.rs
+++ b/src/libextra/crypto/digest.rs
@@ -8,10 +8,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use std::uint;
use std::vec;
+
/**
* The Digest trait specifies an interface common to digest functions, such as SHA-1 and the SHA-2
* family of digest functions.
@@ -28,6 +28,10 @@ pub trait Digest {
/**
* Retrieve the digest result. This method may be called multiple times.
+ *
+ * # Arguments
+ *
+ * * out - the vector to hold the result. Must be large enough to contain output_bits().
*/
fn result(&mut self, out: &mut [u8]);
@@ -41,23 +45,7 @@ pub trait Digest {
* Get the output size in bits.
*/
fn output_bits(&self) -> uint;
-}
-
-fn to_hex(rr: &[u8]) -> ~str {
- let mut s = ~"";
- for rr.iter().advance() |b| {
- let hex = uint::to_str_radix(*b as uint, 16u);
- if hex.len() == 1 {
- s.push_char('0');
- }
- s.push_str(hex);
- }
- return s;
-}
-/// Contains utility methods for Digests.
-/// FIXME: #7339: Convert to default methods when issues with them are resolved.
-pub trait DigestUtil {
/**
* Convenience functon that feeds a string into a digest
*
@@ -65,23 +53,29 @@ pub trait DigestUtil {
*
* * in The string to feed into the digest
*/
- fn input_str(&mut self, in: &str);
+ fn input_str(&mut self, in: &str) {
+ self.input(in.as_bytes());
+ }
/**
* Convenience functon that retrieves the result of a digest as a
* ~str in hexadecimal format.
*/
- fn result_str(&mut self) -> ~str;
-}
-
-impl
Date: Mon, 29 Jul 2013 21:12:20 -0400
Subject: [PATCH 7/9] Crypto: Add large input tests for all Digests
Create a helper function in cryptoutil.rs which feeds 1,000,000 'a's into
a Digest with varying input sizes and then checks the result. This is
essentially the same as one of Sha1's existing tests, so, that test was
re-implemented using this method. New tests were added using this method for
Sha512 and Sha256.
---
src/libextra/crypto/cryptoutil.rs | 33 +++++++++++++++++++++++++++++++
src/libextra/crypto/sha1.rs | 31 ++++++++++-------------------
src/libextra/crypto/sha2.rs | 20 +++++++++++++++++++
3 files changed, 63 insertions(+), 21 deletions(-)
diff --git a/src/libextra/crypto/cryptoutil.rs b/src/libextra/crypto/cryptoutil.rs
index 71e27a56083b7..02f8074f30617 100644
--- a/src/libextra/crypto/cryptoutil.rs
+++ b/src/libextra/crypto/cryptoutil.rs
@@ -241,3 +241,36 @@ impl
Date: Tue, 30 Jul 2013 00:07:51 -0400
Subject: [PATCH 8/9] Crypto: Add overflow checking addition functions.
Added functions to cryptoutil.rs that perform an addition after shifting
the 2nd parameter by a specified constant. These function fail!() if integer
overflow will result. Updated the Sha2 implementation to use these functions.
---
src/libextra/crypto/cryptoutil.rs | 51 +++++++++++++++++++++
src/libextra/crypto/sha2.rs | 75 +++++++++----------------------
2 files changed, 71 insertions(+), 55 deletions(-)
diff --git a/src/libextra/crypto/cryptoutil.rs b/src/libextra/crypto/cryptoutil.rs
index 02f8074f30617..80f5ddb37db87 100644
--- a/src/libextra/crypto/cryptoutil.rs
+++ b/src/libextra/crypto/cryptoutil.rs
@@ -8,6 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use std::num::One;
use std::vec::bytes::{MutableByteVector, copy_memory};
@@ -68,6 +69,56 @@ pub fn read_u32v_be(dst: &mut[u32], in: &[u8]) {
}
+/// Returns true if adding the two parameters will result in integer overflow
+pub fn will_add_overflow
Date: Tue, 30 Jul 2013 00:07:59 -0400
Subject: [PATCH 9/9] Sha1: Update Sha1 to use new functionality in
cryptoutil.rs
---
src/libextra/crypto/sha1.rs | 138 ++++++++++--------------------------
1 file changed, 37 insertions(+), 101 deletions(-)
diff --git a/src/libextra/crypto/sha1.rs b/src/libextra/crypto/sha1.rs
index 7246b8e351839..56fba9790f001 100644
--- a/src/libextra/crypto/sha1.rs
+++ b/src/libextra/crypto/sha1.rs
@@ -23,6 +23,8 @@
*/
+use cryptoutil::{write_u32_be, read_u32v_be, shift_add_check_overflow, FixedBuffer, FixedBuffer64,
+ StandardPadding};
use digest::Digest;
/*
@@ -33,7 +35,6 @@ use digest::Digest;
// Some unexported constants
static DIGEST_BUF_LEN: uint = 5u;
-static MSG_BLOCK_LEN: uint = 64u;
static WORK_BUF_LEN: uint = 80u;
static K0: u32 = 0x5A827999u32;
static K1: u32 = 0x6ED9EBA1u32;
@@ -43,58 +44,38 @@ static K3: u32 = 0xCA62C1D6u32;
/// Structure representing the state of a Sha1 computation
pub struct Sha1 {
priv h: [u32, ..DIGEST_BUF_LEN],
- priv len_low: u32,
- priv len_high: u32,
- priv msg_block: [u8, ..MSG_BLOCK_LEN],
- priv msg_block_idx: uint,
+ priv length_bits: u64,
+ priv buffer: FixedBuffer64,
priv computed: bool,
- priv work_buf: [u32, ..WORK_BUF_LEN]
}
fn add_input(st: &mut Sha1, msg: &[u8]) {
assert!((!st.computed));
- for msg.iter().advance |element| {
- st.msg_block[st.msg_block_idx] = *element;
- st.msg_block_idx += 1;
- st.len_low += 8;
- if st.len_low == 0 {
- st.len_high += 1;
- if st.len_high == 0 {
- // FIXME: Need better failure mode (#2346)
- fail!();
- }
- }
- if st.msg_block_idx == MSG_BLOCK_LEN { process_msg_block(st); }
- }
+ // Assumes that in.len() can be converted to u64 without overflow
+ st.length_bits = shift_add_check_overflow(st.length_bits, msg.len() as u64, 3);
+ st.buffer.input(msg, |d: &[u8]| { process_msg_block(d, &mut st.h); });
}
-fn process_msg_block(st: &mut Sha1) {
+fn process_msg_block(data: &[u8], h: &mut [u32, ..DIGEST_BUF_LEN]) {
let mut t: int; // Loop counter
- let mut w = st.work_buf;
+
+ let mut w = [0u32, ..WORK_BUF_LEN];
// Initialize the first 16 words of the vector w
- t = 0;
- while t < 16 {
- let mut tmp;
- tmp = (st.msg_block[t * 4] as u32) << 24u32;
- tmp = tmp | (st.msg_block[t * 4 + 1] as u32) << 16u32;
- tmp = tmp | (st.msg_block[t * 4 + 2] as u32) << 8u32;
- tmp = tmp | (st.msg_block[t * 4 + 3] as u32);
- w[t] = tmp;
- t += 1;
- }
+ read_u32v_be(w.mut_slice(0, 16), data);
// Initialize the rest of vector w
+ t = 16;
while t < 80 {
let val = w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16];
w[t] = circular_shift(1, val);
t += 1;
}
- let mut a = st.h[0];
- let mut b = st.h[1];
- let mut c = st.h[2];
- let mut d = st.h[3];
- let mut e = st.h[4];
+ let mut a = h[0];
+ let mut b = h[1];
+ let mut c = h[2];
+ let mut d = h[3];
+ let mut e = h[4];
let mut temp: u32;
t = 0;
while t < 20 {
@@ -135,12 +116,11 @@ fn process_msg_block(st: &mut Sha1) {
a = temp;
t += 1;
}
- st.h[0] = st.h[0] + a;
- st.h[1] = st.h[1] + b;
- st.h[2] = st.h[2] + c;
- st.h[3] = st.h[3] + d;
- st.h[4] = st.h[4] + e;
- st.msg_block_idx = 0;
+ h[0] += a;
+ h[1] += b;
+ h[2] += c;
+ h[3] += d;
+ h[4] += e;
}
fn circular_shift(bits: u32, word: u32) -> u32 {
@@ -148,60 +128,20 @@ fn circular_shift(bits: u32, word: u32) -> u32 {
}
fn mk_result(st: &mut Sha1, rs: &mut [u8]) {
- if !st.computed { pad_msg(st); st.computed = true; }
- let mut i = 0;
- for st.h.mut_iter().advance |ptr_hpart| {
- let hpart = *ptr_hpart;
- rs[i] = (hpart >> 24u32 & 0xFFu32) as u8;
- rs[i+1] = (hpart >> 16u32 & 0xFFu32) as u8;
- rs[i+2] = (hpart >> 8u32 & 0xFFu32) as u8;
- rs[i+3] = (hpart & 0xFFu32) as u8;
- i += 4;
- }
-}
+ if !st.computed {
+ st.buffer.standard_padding(8, |d: &[u8]| { process_msg_block(d, &mut st.h) });
+ write_u32_be(st.buffer.next(4), (st.length_bits >> 32) as u32 );
+ write_u32_be(st.buffer.next(4), st.length_bits as u32);
+ process_msg_block(st.buffer.full_buffer(), &mut st.h);
-/*
- * According to the standard, the message must be padded to an even
- * 512 bits. The first padding bit must be a '1'. The last 64 bits
- * represent the length of the original message. All bits in between
- * should be 0. This function will pad the message according to those
- * rules by filling the msg_block vector accordingly. It will also
- * call process_msg_block() appropriately. When it returns, it
- * can be assumed that the message digest has been computed.
- */
-fn pad_msg(st: &mut Sha1) {
- /*
- * Check to see if the current message block is too small to hold
- * the initial padding bits and length. If so, we will pad the
- * block, process it, and then continue padding into a second block.
- */
- if st.msg_block_idx > 55 {
- st.msg_block[st.msg_block_idx] = 0x80;
- st.msg_block_idx += 1;
- while st.msg_block_idx < MSG_BLOCK_LEN {
- st.msg_block[st.msg_block_idx] = 0;
- st.msg_block_idx += 1;
- }
- process_msg_block(st);
- } else {
- st.msg_block[st.msg_block_idx] = 0x80;
- st.msg_block_idx += 1;
- }
- while st.msg_block_idx < 56 {
- st.msg_block[st.msg_block_idx] = 0u8;
- st.msg_block_idx += 1;
+ st.computed = true;
}
- // Store the message length as the last 8 octets
- st.msg_block[56] = (st.len_high >> 24u32 & 0xFFu32) as u8;
- st.msg_block[57] = (st.len_high >> 16u32 & 0xFFu32) as u8;
- st.msg_block[58] = (st.len_high >> 8u32 & 0xFFu32) as u8;
- st.msg_block[59] = (st.len_high & 0xFFu32) as u8;
- st.msg_block[60] = (st.len_low >> 24u32 & 0xFFu32) as u8;
- st.msg_block[61] = (st.len_low >> 16u32 & 0xFFu32) as u8;
- st.msg_block[62] = (st.len_low >> 8u32 & 0xFFu32) as u8;
- st.msg_block[63] = (st.len_low & 0xFFu32) as u8;
- process_msg_block(st);
+ write_u32_be(rs.mut_slice(0, 4), st.h[0]);
+ write_u32_be(rs.mut_slice(4, 8), st.h[1]);
+ write_u32_be(rs.mut_slice(8, 12), st.h[2]);
+ write_u32_be(rs.mut_slice(12, 16), st.h[3]);
+ write_u32_be(rs.mut_slice(16, 20), st.h[4]);
}
impl Sha1 {
@@ -209,12 +149,9 @@ impl Sha1 {
pub fn new() -> Sha1 {
let mut st = Sha1 {
h: [0u32, ..DIGEST_BUF_LEN],
- len_low: 0u32,
- len_high: 0u32,
- msg_block: [0u8, ..MSG_BLOCK_LEN],
- msg_block_idx: 0,
+ length_bits: 0u64,
+ buffer: FixedBuffer64::new(),
computed: false,
- work_buf: [0u32, ..WORK_BUF_LEN]
};
st.reset();
return st;
@@ -223,14 +160,13 @@ impl Sha1 {
impl Digest for Sha1 {
pub fn reset(&mut self) {
- self.len_low = 0;
- self.len_high = 0;
- self.msg_block_idx = 0;
+ self.length_bits = 0;
self.h[0] = 0x67452301u32;
self.h[1] = 0xEFCDAB89u32;
self.h[2] = 0x98BADCFEu32;
self.h[3] = 0x10325476u32;
self.h[4] = 0xC3D2E1F0u32;
+ self.buffer.reset();
self.computed = false;
}
pub fn input(&mut self, msg: &[u8]) { add_input(self, msg); }