File Coverage

/usr/local/lib/perl5/site_perl/5.26.1/x86_64-linux/CPP/Boost/Mini.x/i/boost/uuid/detail/sha1.hpp
Criterion Covered Total %
statement 94 102 92.1
branch 20 28 71.4
condition n/a
subroutine n/a
pod n/a
total 114 130 87.6


line stmt bran cond sub pod time code
1             // boost/uuid/sha1.hpp header file ----------------------------------------------//
2              
3             // Copyright 2007 Andy Tompkins.
4             // Distributed under the Boost Software License, Version 1.0. (See
5             // accompanying file LICENSE_1_0.txt or copy at
6             // http://www.boost.org/LICENSE_1_0.txt)
7              
8             // Revision History
9             // 29 May 2007 - Initial Revision
10             // 25 Feb 2008 - moved to namespace boost::uuids::detail
11             // 10 Jan 2012 - can now handle the full size of messages (2^64 - 1 bits)
12              
13             // This is a byte oriented implementation
14              
15             #ifndef BOOST_UUID_SHA1_H
16             #define BOOST_UUID_SHA1_H
17              
18             #include
19             #include
20             #include // for version
21             #include
22             #include
23             #include
24              
25             #ifdef BOOST_NO_STDC_NAMESPACE
26             namespace std {
27             using ::size_t;
28             } // namespace std
29             #endif
30              
31             namespace boost {
32             namespace uuids {
33             namespace detail {
34              
35             BOOST_STATIC_ASSERT(sizeof(unsigned char)*8 == 8);
36             BOOST_STATIC_ASSERT(sizeof(unsigned int)*8 == 32);
37              
38 448           inline unsigned int left_rotate(unsigned int x, std::size_t n)
39             {
40 448           return (x<> (32-n));
41             }
42              
43             class sha1
44             {
45             public:
46             typedef unsigned int(digest_type)[5];
47             public:
48             sha1();
49              
50             void reset();
51              
52             void process_byte(unsigned char byte);
53             void process_block(void const* bytes_begin, void const* bytes_end);
54             void process_bytes(void const* buffer, std::size_t byte_count);
55              
56             void get_digest(digest_type& digest);
57             unsigned char get_version() const;
58              
59             private:
60             void process_block();
61             void process_byte_impl(unsigned char byte);
62              
63             private:
64             unsigned int h_[5];
65              
66             unsigned char block_[64];
67              
68             std::size_t block_byte_index_;
69             std::size_t bit_count_low;
70             std::size_t bit_count_high;
71             };
72              
73 2           inline sha1::sha1()
74             {
75 2           reset();
76 2           }
77              
78 2           inline void sha1::reset()
79             {
80 2           h_[0] = 0x67452301;
81 2           h_[1] = 0xEFCDAB89;
82 2           h_[2] = 0x98BADCFE;
83 2           h_[3] = 0x10325476;
84 2           h_[4] = 0xC3D2E1F0;
85              
86 2           block_byte_index_ = 0;
87 2           bit_count_low = 0;
88 2           bit_count_high = 0;
89 2           }
90              
91 45           inline void sha1::process_byte(unsigned char byte)
92             {
93 45           process_byte_impl(byte);
94              
95             // size_t max value = 0xFFFFFFFF
96             //if (bit_count_low + 8 >= 0x100000000) { // would overflow
97             //if (bit_count_low >= 0x100000000-8) {
98 45 50         if (bit_count_low < 0xFFFFFFF8) {
99 45           bit_count_low += 8;
100             } else {
101 0           bit_count_low = 0;
102              
103 0 0         if (bit_count_high <= 0xFFFFFFFE) {
104 0           ++bit_count_high;
105             } else {
106 0           BOOST_THROW_EXCEPTION(std::runtime_error("sha1 too many bytes"));
107             }
108             }
109 45           }
110              
111 128           inline void sha1::process_byte_impl(unsigned char byte)
112             {
113 128           block_[block_byte_index_++] = byte;
114              
115 128 100         if (block_byte_index_ == 64) {
116 2           block_byte_index_ = 0;
117 2           process_block();
118             }
119 128           }
120              
121 4           inline void sha1::process_block(void const* bytes_begin, void const* bytes_end)
122             {
123 4           unsigned char const* begin = static_cast(bytes_begin);
124 4           unsigned char const* end = static_cast(bytes_end);
125 49 100         for(; begin != end; ++begin) {
126 45           process_byte(*begin);
127             }
128 4           }
129              
130 4           inline void sha1::process_bytes(void const* buffer, std::size_t byte_count)
131             {
132 4           unsigned char const* b = static_cast(buffer);
133 4           process_block(b, b+byte_count);
134 4           }
135              
136 2           inline void sha1::process_block()
137             {
138             unsigned int w[80];
139 34 100         for (std::size_t i=0; i<16; ++i) {
140 32           w[i] = (block_[i*4 + 0] << 24);
141 32           w[i] |= (block_[i*4 + 1] << 16);
142 32           w[i] |= (block_[i*4 + 2] << 8);
143 32           w[i] |= (block_[i*4 + 3]);
144             }
145 130 100         for (std::size_t i=16; i<80; ++i) {
146 128           w[i] = left_rotate((w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]), 1);
147             }
148              
149 2           unsigned int a = h_[0];
150 2           unsigned int b = h_[1];
151 2           unsigned int c = h_[2];
152 2           unsigned int d = h_[3];
153 2           unsigned int e = h_[4];
154              
155 162 100         for (std::size_t i=0; i<80; ++i) {
156             unsigned int f;
157             unsigned int k;
158              
159 160 100         if (i<20) {
160 40           f = (b & c) | (~b & d);
161 40           k = 0x5A827999;
162 120 100         } else if (i<40) {
163 40           f = b ^ c ^ d;
164 40           k = 0x6ED9EBA1;
165 80 100         } else if (i<60) {
166 40           f = (b & c) | (b & d) | (c & d);
167 40           k = 0x8F1BBCDC;
168             } else {
169 40           f = b ^ c ^ d;
170 40           k = 0xCA62C1D6;
171             }
172              
173 160           unsigned temp = left_rotate(a, 5) + f + e + k + w[i];
174 160           e = d;
175 160           d = c;
176 160           c = left_rotate(b, 30);
177 160           b = a;
178 160           a = temp;
179             }
180              
181 2           h_[0] += a;
182 2           h_[1] += b;
183 2           h_[2] += c;
184 2           h_[3] += d;
185 2           h_[4] += e;
186 2           }
187              
188 2           inline unsigned char sha1::get_version() const
189             {
190             // RFC 4122 Section 4.1.3
191 2           return uuid::version_name_based_sha1;
192             }
193              
194 2           inline void sha1::get_digest(digest_type& digest)
195             {
196             // append the bit '1' to the message
197 2           process_byte_impl(0x80);
198              
199             // append k bits '0', where k is the minimum number >= 0
200             // such that the resulting message length is congruent to 56 (mod 64)
201             // check if there is enough space for padding and bit_count
202 2 50         if (block_byte_index_ > 56) {
203             // finish this block
204 0 0         while (block_byte_index_ != 0) {
205 0           process_byte_impl(0);
206             }
207              
208             // one more block
209 0 0         while (block_byte_index_ < 56) {
210 0           process_byte_impl(0);
211             }
212             } else {
213 67 100         while (block_byte_index_ < 56) {
214 65           process_byte_impl(0);
215             }
216             }
217              
218             // append length of message (before pre-processing)
219             // as a 64-bit big-endian integer
220 2           process_byte_impl( static_cast((bit_count_high>>24) & 0xFF) );
221 2           process_byte_impl( static_cast((bit_count_high>>16) & 0xFF) );
222 2           process_byte_impl( static_cast((bit_count_high>>8 ) & 0xFF) );
223 2           process_byte_impl( static_cast((bit_count_high) & 0xFF) );
224 2           process_byte_impl( static_cast((bit_count_low>>24) & 0xFF) );
225 2           process_byte_impl( static_cast((bit_count_low>>16) & 0xFF) );
226 2           process_byte_impl( static_cast((bit_count_low>>8 ) & 0xFF) );
227 2           process_byte_impl( static_cast((bit_count_low) & 0xFF) );
228              
229             // get final digest
230 2           digest[0] = h_[0];
231 2           digest[1] = h_[1];
232 2           digest[2] = h_[2];
233 2           digest[3] = h_[3];
234 2           digest[4] = h_[4];
235 2           }
236              
237             }}} // namespace boost::uuids::detail
238              
239             #endif