Coverage Report

Created: 2026-02-13 06:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/resiprocate/rutil/Sha1.cxx
Line
Count
Source
1
/*
2
    Original Source code contained this header:
3
4
    sha1.cpp - source code of
5
6
    ============
7
    SHA-1 in C++
8
    ============
9
10
    100% Public Domain.
11
12
    Original C Code
13
        -- Steve Reid <steve@edmweb.com>
14
    Small changes to fit into bglibs
15
        -- Bruce Guenter <bruce@untroubled.org>
16
    Translation to simpler C++ Code
17
        -- Volker Grabsch <vog@notjusthosting.com>
18
*/
19
20
#include "Sha1.hxx"
21
#include <sstream>
22
#include <iomanip>
23
#include <fstream>
24
25
using namespace resip;
26
27
Sha1::Sha1()
28
0
{
29
0
    reset();
30
0
}
31
32
33
void Sha1::update(const std::string &s)
34
0
{
35
0
    std::istringstream is(s);
36
0
    update(is);
37
0
}
38
39
40
void Sha1::update(std::istream &is)
41
0
{
42
0
    std::string rest_of_buffer;
43
0
    read(is, rest_of_buffer, BLOCK_BYTES - (int)buffer.size());
44
0
    buffer += rest_of_buffer;
45
46
0
    while (is)
47
0
    {
48
0
        uint32_t block[BLOCK_INTS];
49
0
        buffer_to_block(buffer, block);
50
0
        transform(block);
51
0
        read(is, buffer, BLOCK_BYTES);
52
0
    }
53
0
}
54
55
56
/*
57
 * Add padding and return the message digest.
58
 */
59
60
std::string Sha1::final()
61
0
{
62
    /* Use input and create digest */
63
0
    createDigest();
64
65
    /* Hex std::string */
66
0
    std::ostringstream result;
67
0
    for (unsigned int i = 0; i < DIGEST_INTS; i++)
68
0
    {
69
0
        result << std::hex << std::setfill('0') << std::setw(8);
70
0
        result << (digest[i] & 0xffffffff);
71
0
    }
72
73
    /* Reset for next run */
74
0
    reset();
75
76
0
    return result.str();
77
0
}
78
79
resip::Data Sha1::finalBin()
80
0
{
81
    /* Use input and create digest */
82
0
    createDigest();
83
84
0
    resip::Data result(21, Data::Preallocate);  // Data likes a NULL at the end use 21 instead of 20
85
0
    for (unsigned int i = 0; i < DIGEST_INTS; i++)
86
0
    {
87
0
        uint32_t digesttemp = htonl(digest[i]);
88
0
        result.append((const char*)&digesttemp, sizeof(digest[0]));
89
0
    }
90
91
    /* Reset for next run */
92
0
    reset();
93
94
0
    return result;
95
0
}
96
97
void Sha1::createDigest()
98
0
{
99
    /* Total number of hashed bits */
100
0
    uint64_t total_bits = (transforms*BLOCK_BYTES + buffer.size()) * 8;
101
102
    /* Padding */
103
0
    buffer += (char)0x80;
104
0
    unsigned int orig_size = (unsigned int)buffer.size();
105
0
    while (buffer.size() < BLOCK_BYTES)
106
0
    {
107
0
        buffer += (char)0x00;
108
0
    }
109
110
0
    uint32_t block[BLOCK_INTS];
111
0
    buffer_to_block(buffer, block);
112
113
0
    if (orig_size > BLOCK_BYTES - 8)
114
0
    {
115
0
        transform(block);
116
0
        for (unsigned int i = 0; i < BLOCK_INTS - 2; i++)
117
0
        {
118
0
            block[i] = 0;
119
0
        }
120
0
    }
121
122
    /* Append total_bits, split this uint64_t into two uint32_t */
123
0
    block[BLOCK_INTS - 1] = (uint32_t)total_bits;
124
0
    block[BLOCK_INTS - 2] = (total_bits >> 32);
125
0
    transform(block);
126
0
}
127
128
std::string Sha1::from_file(const std::string &filename)
129
0
{
130
0
    std::ifstream stream(filename.c_str(), std::ios::binary);
131
0
    Sha1 checksum;
132
0
    checksum.update(stream);
133
0
    return checksum.final();
134
0
}
135
136
137
void Sha1::reset()
138
0
{
139
    /* SHA1 initialization constants */
140
0
    digest[0] = 0x67452301;
141
0
    digest[1] = 0xefcdab89;
142
0
    digest[2] = 0x98badcfe;
143
0
    digest[3] = 0x10325476;
144
0
    digest[4] = 0xc3d2e1f0;
145
146
    /* Reset counters */
147
0
    transforms = 0;
148
0
    buffer = "";
149
0
}
150
151
152
/*
153
 * Hash a single 512-bit block. This is the core of the algorithm.
154
 */
155
156
void Sha1::transform(uint32_t block[BLOCK_BYTES])
157
0
{
158
    /* Copy digest[] to working vars */
159
0
    uint32_t a = digest[0];
160
0
    uint32_t b = digest[1];
161
0
    uint32_t c = digest[2];
162
0
    uint32_t d = digest[3];
163
0
    uint32_t e = digest[4];
164
165
    /* Help macros */
166
0
#define rol(value, bits) (((value) << (bits)) | (((value) & 0xffffffff) >> (32 - (bits))))
167
0
#define blk(i) (block[i&15] = rol(block[(i+13)&15] ^ block[(i+8)&15] ^ block[(i+2)&15] ^ block[i&15],1))
168
169
    /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
170
0
#define R0(v,w,x,y,z,i) z += ((w&(x^y))^y)     + block[i] + 0x5a827999 + rol(v,5); w=rol(w,30);
171
0
#define R1(v,w,x,y,z,i) z += ((w&(x^y))^y)     + blk(i)   + 0x5a827999 + rol(v,5); w=rol(w,30);
172
0
#define R2(v,w,x,y,z,i) z += (w^x^y)           + blk(i)   + 0x6ed9eba1 + rol(v,5); w=rol(w,30);
173
0
#define R3(v,w,x,y,z,i) z += (((w|x)&y)|(w&x)) + blk(i)   + 0x8f1bbcdc + rol(v,5); w=rol(w,30);
174
0
#define R4(v,w,x,y,z,i) z += (w^x^y)           + blk(i)   + 0xca62c1d6 + rol(v,5); w=rol(w,30);
175
176
    /* 4 rounds of 20 operations each. Loop unrolled. */
177
0
    R0(a,b,c,d,e, 0);
178
0
    R0(e,a,b,c,d, 1);
179
0
    R0(d,e,a,b,c, 2);
180
0
    R0(c,d,e,a,b, 3);
181
0
    R0(b,c,d,e,a, 4);
182
0
    R0(a,b,c,d,e, 5);
183
0
    R0(e,a,b,c,d, 6);
184
0
    R0(d,e,a,b,c, 7);
185
0
    R0(c,d,e,a,b, 8);
186
0
    R0(b,c,d,e,a, 9);
187
0
    R0(a,b,c,d,e,10);
188
0
    R0(e,a,b,c,d,11);
189
0
    R0(d,e,a,b,c,12);
190
0
    R0(c,d,e,a,b,13);
191
0
    R0(b,c,d,e,a,14);
192
0
    R0(a,b,c,d,e,15);
193
0
    R1(e,a,b,c,d,16);
194
0
    R1(d,e,a,b,c,17);
195
0
    R1(c,d,e,a,b,18);
196
0
    R1(b,c,d,e,a,19);
197
0
    R2(a,b,c,d,e,20);
198
0
    R2(e,a,b,c,d,21);
199
0
    R2(d,e,a,b,c,22);
200
0
    R2(c,d,e,a,b,23);
201
0
    R2(b,c,d,e,a,24);
202
0
    R2(a,b,c,d,e,25);
203
0
    R2(e,a,b,c,d,26);
204
0
    R2(d,e,a,b,c,27);
205
0
    R2(c,d,e,a,b,28);
206
0
    R2(b,c,d,e,a,29);
207
0
    R2(a,b,c,d,e,30);
208
0
    R2(e,a,b,c,d,31);
209
0
    R2(d,e,a,b,c,32);
210
0
    R2(c,d,e,a,b,33);
211
0
    R2(b,c,d,e,a,34);
212
0
    R2(a,b,c,d,e,35);
213
0
    R2(e,a,b,c,d,36);
214
0
    R2(d,e,a,b,c,37);
215
0
    R2(c,d,e,a,b,38);
216
0
    R2(b,c,d,e,a,39);
217
0
    R3(a,b,c,d,e,40);
218
0
    R3(e,a,b,c,d,41);
219
0
    R3(d,e,a,b,c,42);
220
0
    R3(c,d,e,a,b,43);
221
0
    R3(b,c,d,e,a,44);
222
0
    R3(a,b,c,d,e,45);
223
0
    R3(e,a,b,c,d,46);
224
0
    R3(d,e,a,b,c,47);
225
0
    R3(c,d,e,a,b,48);
226
0
    R3(b,c,d,e,a,49);
227
0
    R3(a,b,c,d,e,50);
228
0
    R3(e,a,b,c,d,51);
229
0
    R3(d,e,a,b,c,52);
230
0
    R3(c,d,e,a,b,53);
231
0
    R3(b,c,d,e,a,54);
232
0
    R3(a,b,c,d,e,55);
233
0
    R3(e,a,b,c,d,56);
234
0
    R3(d,e,a,b,c,57);
235
0
    R3(c,d,e,a,b,58);
236
0
    R3(b,c,d,e,a,59);
237
0
    R4(a,b,c,d,e,60);
238
0
    R4(e,a,b,c,d,61);
239
0
    R4(d,e,a,b,c,62);
240
0
    R4(c,d,e,a,b,63);
241
0
    R4(b,c,d,e,a,64);
242
0
    R4(a,b,c,d,e,65);
243
0
    R4(e,a,b,c,d,66);
244
0
    R4(d,e,a,b,c,67);
245
0
    R4(c,d,e,a,b,68);
246
0
    R4(b,c,d,e,a,69);
247
0
    R4(a,b,c,d,e,70);
248
0
    R4(e,a,b,c,d,71);
249
0
    R4(d,e,a,b,c,72);
250
0
    R4(c,d,e,a,b,73);
251
0
    R4(b,c,d,e,a,74);
252
0
    R4(a,b,c,d,e,75);
253
0
    R4(e,a,b,c,d,76);
254
0
    R4(d,e,a,b,c,77);
255
0
    R4(c,d,e,a,b,78);
256
0
    R4(b,c,d,e,a,79);
257
258
    /* Add the working vars back into digest[] */
259
0
    digest[0] += a;
260
0
    digest[1] += b;
261
0
    digest[2] += c;
262
0
    digest[3] += d;
263
0
    digest[4] += e;
264
265
    /* Count the number of transformations */
266
0
    transforms++;
267
0
}
268
269
270
void Sha1::buffer_to_block(const std::string &buffer, uint32_t block[BLOCK_BYTES])
271
0
{
272
    /* Convert the std::string (byte buffer) to a uint32_t array (MSB) */
273
0
    for (unsigned int i = 0; i < BLOCK_INTS; i++)
274
0
    {
275
0
        block[i] = (buffer[4*i+3] & 0xff)
276
0
                   | (buffer[4*i+2] & 0xff)<<8
277
0
                   | (buffer[4*i+1] & 0xff)<<16
278
0
                   | (buffer[4*i+0] & 0xff)<<24;
279
0
    }
280
0
}
281
282
283
void Sha1::read(std::istream &is, std::string &s, int maxBuffer)
284
0
{
285
0
    char* sbuf = new char[maxBuffer];
286
0
    is.read(sbuf, maxBuffer);
287
0
    s.assign(sbuf, (unsigned int)is.gcount());
288
0
    delete [] sbuf;
289
0
}
290
291
/* ====================================================================
292
 * The Vovida Software License, Version 1.0 
293
 * 
294
 * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
295
 * 
296
 * Redistribution and use in source and binary forms, with or without
297
 * modification, are permitted provided that the following conditions
298
 * are met:
299
 * 
300
 * 1. Redistributions of source code must retain the above copyright
301
 *    notice, this list of conditions and the following disclaimer.
302
 * 
303
 * 2. Redistributions in binary form must reproduce the above copyright
304
 *    notice, this list of conditions and the following disclaimer in
305
 *    the documentation and/or other materials provided with the
306
 *    distribution.
307
 * 
308
 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
309
 *    and "Vovida Open Communication Application Library (VOCAL)" must
310
 *    not be used to endorse or promote products derived from this
311
 *    software without prior written permission. For written
312
 *    permission, please contact vocal@vovida.org.
313
 *
314
 * 4. Products derived from this software may not be called "VOCAL", nor
315
 *    may "VOCAL" appear in their name, without prior written
316
 *    permission of Vovida Networks, Inc.
317
 * 
318
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
319
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
320
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
321
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
322
 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
323
 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
324
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
325
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
326
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
327
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
328
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
329
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
330
 * DAMAGE.
331
 * 
332
 * ====================================================================
333
 * 
334
 * This software consists of voluntary contributions made by Vovida
335
 * Networks, Inc. and many individuals on behalf of Vovida Networks,
336
 * Inc.  For more information on Vovida Networks, Inc., please see
337
 * <http://www.vovida.org/>.
338
 *
339
 */