From a1bbd18dc1f5bf94b5cd4a0ff65c322c57467ebd 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 d713e19297295..c3adf93840605 100644 --- a/src/libextra/crypto/sha2.rs +++ b/src/libextra/crypto/sha2.rs @@ -311,26 +311,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 @@ -575,22 +575,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 5b0155515505f0898d21d2dc49dd30e32a916264 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 c3adf93840605..14618b157c455 100644 --- a/src/libextra/crypto/sha2.rs +++ b/src/libextra/crypto/sha2.rs @@ -10,6 +10,7 @@ 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 @@ -43,6 +44,7 @@ impl BitCounter { } } + // A structure that represents that state of a digest computation // for the SHA-2 512 family of digest functions struct Engine512 { @@ -333,6 +335,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 { @@ -593,134 +820,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. @@ -747,6 +851,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. @@ -773,131 +907,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 3cac62822edf3715afdaa2770333f00f38a51545 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 14618b157c455..2443c93689651 100644 --- a/src/libextra/crypto/sha2.rs +++ b/src/libextra/crypto/sha2.rs @@ -267,48 +267,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. @@ -372,7 +330,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) { @@ -428,7 +396,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) { @@ -484,7 +459,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) { @@ -540,7 +520,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) { @@ -774,31 +759,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] = [ @@ -857,7 +817,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) { @@ -913,7 +882,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 654c536fec01d984f758ec32904354378aa3b792 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 | 757 ++++++++++++------------------
src/libextra/extra.rs | 2 +
3 files changed, 551 insertions(+), 451 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..6e791f90b233f
--- /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 | 193 +++++++++++++++++-------------------
1 file changed, 91 insertions(+), 102 deletions(-)
diff --git a/src/libextra/crypto/sha2.rs b/src/libextra/crypto/sha2.rs
index dc2d56f483e09..fc420d7179fdb 100644
--- a/src/libextra/crypto/sha2.rs
+++ b/src/libextra/crypto/sha2.rs
@@ -8,11 +8,32 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use std::uint;
+
use cryptoutil::{write_u64_be, write_u32_be, read_u64v_be, read_u32v_be, FixedBuffer,
FixedBuffer128, FixedBuffer64, StandardPadding};
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
@@ -117,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);
-
- foreach t in range(16u, 80) {
- 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;
@@ -135,48 +147,41 @@ impl Engine512State {
let mut g = self.H6;
let mut h = self.H7;
- let mut t = 0;
-
- foreach _ in range(0u, 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;
@@ -523,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);
-
- foreach t in range(16u, 64) {
- 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;
@@ -541,48 +537,41 @@ impl Engine256State {
let mut g = self.H6;
let mut h = self.H7;
- let mut t = 0;
-
- foreach _ in range(0u, 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 2cbe312343a31127de9d8e28f7b4ce04bc48768c 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 0efd88fdf5043..217573a4135b0 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 = ~"";
- foreach b in rr.iter() {
- 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, input: &str);
+ fn input_str(&mut self, input: &str) {
+ self.input(input.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 6e791f90b233f..33ab6a9bcb96d 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 33ab6a9bcb96d..43e3b5c89af48 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], input: &[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 0172f6af18e8d..86a89d79f1add 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));
- foreach element in msg.iter() {
- 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 msg.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;
- foreach ptr_hpart in st.h.mut_iter() {
- 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); }