GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/crypto/hash.cc
Date: 2025-04-20 02:34:28
Exec Total Coverage
Lines: 267 298 89.6%
Branches: 169 268 63.1%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5
6 #include "crypto/hash.h"
7
8 #include <alloca.h>
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <openssl/hmac.h>
12 #include <openssl/md5.h>
13 #include <openssl/ripemd.h>
14 #include <openssl/sha.h>
15 #include <unistd.h>
16
17 #include <cstdio>
18 #include <cstring>
19
20 #include "crypto/openssl_version.h"
21 #include "util/exception.h"
22 #include "KeccakHash.h"
23
24
25 using namespace std; // NOLINT
26
27 #ifdef CVMFS_NAMESPACE_GUARD
28 namespace CVMFS_NAMESPACE_GUARD {
29 #endif
30
31 namespace shash {
32
33 const char *kAlgorithmIds[] =
34 {"", "", "-rmd160", "-shake128", ""};
35
36
37 22 bool HexPtr::IsValid() const {
38 22 const unsigned l = str->length();
39
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 21 times.
22 if (l == 0)
40 1 return false;
41 21 const char *c = str->data(); // Walks through the string
42 21 unsigned i = 0; // String position of *c
43
44
2/2
✓ Branch 0 taken 820 times.
✓ Branch 1 taken 5 times.
825 for ( ; i < l; ++i, ++c) {
45
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 806 times.
820 if (*c == '-')
46 14 break;
47
6/8
✓ Branch 0 taken 806 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 806 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 327 times.
✓ Branch 5 taken 479 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 325 times.
806 if ((*c < '0') || (*c > 'f') || ((*c > '9') && (*c < 'a')))
48 2 return false;
49 }
50
51 // Walk through all algorithms
52
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 15 times.
85 for (unsigned j = 0; j < kAny; ++j) {
53 70 const unsigned hex_length = 2*kDigestSizes[j];
54 70 const unsigned algo_id_length = kAlgorithmIdSizes[j];
55
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 48 times.
70 if (i == hex_length) {
56 // Right suffix?
57
4/4
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 53 times.
✓ Branch 3 taken 8 times.
65 for ( ; (i < l) && (i-hex_length < algo_id_length); ++i, ++c) {
58
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 43 times.
53 if (*c != kAlgorithmIds[j][i-hex_length])
59 10 break;
60 }
61
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
22 if ((i == l) && (l == hex_length + algo_id_length))
62 4 return true;
63 18 i = hex_length;
64 18 c = str->data() + i;
65 }
66 }
67
68 15 return false;
69 }
70
71
72 Algorithms ParseHashAlgorithm(const string &algorithm_option) {
73 if (algorithm_option == "sha1")
74 return kSha1;
75 if (algorithm_option == "rmd160")
76 return kRmd160;
77 if (algorithm_option == "shake128")
78 return kShake128;
79 return kAny;
80 }
81
82
83 57131 Any MkFromHexPtr(const HexPtr hex, const char suffix) {
84 57131 Any result;
85
86 57131 const unsigned length = hex.str->length();
87
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 57130 times.
57131 if (length == 2*kDigestSizes[kMd5])
88 1 result = Any(kMd5, hex);
89
2/2
✓ Branch 0 taken 57061 times.
✓ Branch 1 taken 70 times.
57131 if (length == 2*kDigestSizes[kSha1])
90 57061 result = Any(kSha1, hex);
91 // TODO(jblomer) compare -rmd160, -shake128
92
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 57127 times.
57131 if ((length == 2*kDigestSizes[kRmd160] + kAlgorithmIdSizes[kRmd160]))
93 4 result = Any(kRmd160, hex);
94
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 57126 times.
57131 if ((length == 2*kDigestSizes[kShake128] + kAlgorithmIdSizes[kShake128]))
95 5 result = Any(kShake128, hex);
96
97 57131 result.suffix = suffix;
98 57131 return result;
99 }
100
101
102 /**
103 * Similar to MkFromHexPtr but the suffix is deducted from the HexPtr string.
104 */
105 43726 Any MkFromSuffixedHexPtr(const HexPtr hex) {
106 43726 Any result;
107
108 43726 const unsigned length = hex.str->length();
109
4/4
✓ Branch 0 taken 429 times.
✓ Branch 1 taken 43297 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 428 times.
43726 if ((length == 2*kDigestSizes[kMd5]) || (length == 2*kDigestSizes[kMd5] + 1))
110 {
111
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 43297 times.
43299 Suffix suffix = (length == 2*kDigestSizes[kMd5] + 1) ?
112 1 *(hex.str->rbegin()) : kSuffixNone;
113 43298 result = Any(kMd5, hex, suffix);
114 }
115
2/2
✓ Branch 0 taken 43484 times.
✓ Branch 1 taken 242 times.
43726 if ((length == 2*kDigestSizes[kSha1]) ||
116
2/2
✓ Branch 0 taken 169 times.
✓ Branch 1 taken 43315 times.
43484 (length == 2*kDigestSizes[kSha1] + 1))
117 {
118
2/2
✓ Branch 0 taken 169 times.
✓ Branch 1 taken 242 times.
580 Suffix suffix = (length == 2*kDigestSizes[kSha1] + 1) ?
119 169 *(hex.str->rbegin()) : kSuffixNone;
120 411 result = Any(kSha1, hex, suffix);
121 }
122
2/2
✓ Branch 0 taken 43725 times.
✓ Branch 1 taken 1 times.
43726 if ((length == 2*kDigestSizes[kRmd160] + kAlgorithmIdSizes[kRmd160]) ||
123
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 43712 times.
43725 (length == 2*kDigestSizes[kRmd160] + kAlgorithmIdSizes[kRmd160] + 1))
124 {
125 Suffix suffix =
126 14 (length == 2*kDigestSizes[kRmd160] + kAlgorithmIdSizes[kRmd160] + 1)
127
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1 times.
14 ? *(hex.str->rbegin())
128 14 : kSuffixNone;
129 14 result = Any(kRmd160, hex, suffix);
130 }
131
2/2
✓ Branch 0 taken 43725 times.
✓ Branch 1 taken 1 times.
43726 if ((length == 2*kDigestSizes[kShake128] + kAlgorithmIdSizes[kShake128]) ||
132
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 43724 times.
43725 (length == 2*kDigestSizes[kShake128] + kAlgorithmIdSizes[kShake128] + 1))
133 {
134 Suffix suffix =
135 2 (length == 2*kDigestSizes[kShake128] + kAlgorithmIdSizes[kShake128] + 1)
136
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 ? *(hex.str->rbegin())
137 2 : kSuffixNone;
138 2 result = Any(kShake128, hex, suffix);
139 }
140
141 43726 return result;
142 }
143
144
145 /**
146 * Allows the caller to create the context on the stack.
147 */
148 1515751 unsigned GetContextSize(const Algorithms algorithm) {
149
4/5
✓ Branch 0 taken 1217588 times.
✓ Branch 1 taken 297250 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 911 times.
✗ Branch 4 not taken.
1515751 switch (algorithm) {
150 1217588 case kMd5:
151 1217588 return sizeof(MD5_CTX);
152 297250 case kSha1:
153 297250 return sizeof(SHA_CTX);
154 14 case kRmd160:
155 14 return sizeof(RIPEMD160_CTX);
156 911 case kShake128:
157 911 return sizeof(Keccak_HashInstance);
158 default:
159 PANIC(kLogDebug | kLogSyslogErr,
160 "tried to generate hash context for unspecified hash. Aborting...");
161 }
162 }
163
164 1515800 void Init(ContextPtr context) {
165 HashReturn keccak_result;
166
4/5
✓ Branch 0 taken 1217600 times.
✓ Branch 1 taken 297278 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 911 times.
✗ Branch 4 not taken.
1515800 switch (context.algorithm) {
167 1217600 case kMd5:
168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1217600 times.
1217600 assert(context.size == sizeof(MD5_CTX));
169 1217600 MD5_Init(reinterpret_cast<MD5_CTX *>(context.buffer));
170 1217600 break;
171 297278 case kSha1:
172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 297278 times.
297278 assert(context.size == sizeof(SHA_CTX));
173 297278 SHA1_Init(reinterpret_cast<SHA_CTX *>(context.buffer));
174 297190 break;
175 14 case kRmd160:
176
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 assert(context.size == sizeof(RIPEMD160_CTX));
177 14 RIPEMD160_Init(reinterpret_cast<RIPEMD160_CTX *>(context.buffer));
178 14 break;
179 911 case kShake128:
180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 911 times.
911 assert(context.size == sizeof(Keccak_HashInstance));
181 911 keccak_result = Keccak_HashInitialize_SHAKE128(
182 reinterpret_cast<Keccak_HashInstance *>(context.buffer));
183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 911 times.
911 assert(keccak_result == SUCCESS);
184 911 break;
185 default:
186 PANIC(NULL); // Undefined hash
187 }
188 1515715 }
189
190 99832151 void Update(const unsigned char *buffer, const unsigned buffer_length,
191 ContextPtr context)
192 {
193 HashReturn keccak_result;
194
4/5
✓ Branch 0 taken 29980967 times.
✓ Branch 1 taken 23712922 times.
✓ Branch 2 taken 23068688 times.
✓ Branch 3 taken 23069577 times.
✗ Branch 4 not taken.
99832151 switch (context.algorithm) {
195 29980967 case kMd5:
196
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29980967 times.
29980967 assert(context.size == sizeof(MD5_CTX));
197 29980967 MD5_Update(reinterpret_cast<MD5_CTX *>(context.buffer),
198 buffer, buffer_length);
199 29980967 break;
200 23712922 case kSha1:
201
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23712922 times.
23712922 assert(context.size == sizeof(SHA_CTX));
202 23712922 SHA1_Update(reinterpret_cast<SHA_CTX *>(context.buffer),
203 buffer, buffer_length);
204 23713854 break;
205 23068688 case kRmd160:
206
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23068688 times.
23068688 assert(context.size == sizeof(RIPEMD160_CTX));
207 23068688 RIPEMD160_Update(reinterpret_cast<RIPEMD160_CTX *>(context.buffer),
208 buffer, buffer_length);
209 23068688 break;
210 23069577 case kShake128:
211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23069577 times.
23069577 assert(context.size == sizeof(Keccak_HashInstance));
212 46139154 keccak_result = Keccak_HashUpdate(reinterpret_cast<Keccak_HashInstance *>(
213 23069577 context.buffer), buffer, buffer_length * 8);
214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23069577 times.
23069577 assert(keccak_result == SUCCESS);
215 23069577 break;
216 default:
217 PANIC(NULL); // Undefined hash
218 }
219 99833086 }
220
221 1494555 void Final(ContextPtr context, Any *any_digest) {
222 HashReturn keccak_result;
223
4/5
✓ Branch 0 taken 1217584 times.
✓ Branch 1 taken 276049 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 911 times.
✗ Branch 4 not taken.
1494555 switch (context.algorithm) {
224 1217584 case kMd5:
225
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1217584 times.
1217584 assert(context.size == sizeof(MD5_CTX));
226 1217584 MD5_Final(any_digest->digest,
227 1217584 reinterpret_cast<MD5_CTX *>(context.buffer));
228 1217584 break;
229 276049 case kSha1:
230
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 276049 times.
276049 assert(context.size == sizeof(SHA_CTX));
231 276049 SHA1_Final(any_digest->digest,
232 276049 reinterpret_cast<SHA_CTX *>(context.buffer));
233 277550 break;
234 14 case kRmd160:
235
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 assert(context.size == sizeof(RIPEMD160_CTX));
236 14 RIPEMD160_Final(any_digest->digest,
237 14 reinterpret_cast<RIPEMD160_CTX *>(context.buffer));
238 14 break;
239 911 case kShake128:
240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 911 times.
911 assert(context.size == sizeof(Keccak_HashInstance));
241 1822 keccak_result = Keccak_HashFinal(reinterpret_cast<Keccak_HashInstance *>(
242 911 context.buffer), NULL);
243
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 911 times.
911 assert(keccak_result == SUCCESS);
244 keccak_result =
245 1822 Keccak_HashSqueeze(reinterpret_cast<Keccak_HashInstance *>(
246 911 context.buffer), any_digest->digest, kDigestSizes[kShake128] * 8);
247 911 break;
248 default:
249 PANIC(NULL); // Undefined hash
250 }
251 1496059 any_digest->algorithm = context.algorithm;
252 1496059 }
253
254
255 17129 void HashMem(const unsigned char *buffer, const unsigned buffer_size,
256 Any *any_digest)
257 {
258 17129 Algorithms algorithm = any_digest->algorithm;
259
1/2
✓ Branch 1 taken 17129 times.
✗ Branch 2 not taken.
17129 ContextPtr context(algorithm);
260 17129 context.buffer = alloca(context.size);
261
262
1/2
✓ Branch 1 taken 17129 times.
✗ Branch 2 not taken.
17129 Init(context);
263
1/2
✓ Branch 1 taken 17129 times.
✗ Branch 2 not taken.
17129 Update(buffer, buffer_size, context);
264
1/2
✓ Branch 1 taken 17129 times.
✗ Branch 2 not taken.
17129 Final(context, any_digest);
265 17129 }
266
267
268 1081 void HashString(const std::string &content, Any *any_digest) {
269 1081 HashMem(reinterpret_cast<const unsigned char *>(content.data()),
270 1081 content.length(), any_digest);
271 1081 }
272
273
274 607387 void Hmac(
275 const string &key,
276 const unsigned char *buffer,
277 const unsigned buffer_size,
278 Any *any_digest
279 ) {
280 607387 Algorithms algorithm = any_digest->algorithm;
281
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 607387 times.
607387 assert(algorithm != kAny);
282
283 607387 const unsigned block_size = kBlockSizes[algorithm];
284 607387 unsigned char key_block[block_size];
285 607387 memset(key_block, 0, block_size);
286
2/2
✓ Branch 1 taken 7332 times.
✓ Branch 2 taken 600055 times.
607387 if (key.length() > block_size) {
287
1/2
✓ Branch 1 taken 7332 times.
✗ Branch 2 not taken.
7332 Any hash_key(algorithm);
288
1/2
✓ Branch 2 taken 7332 times.
✗ Branch 3 not taken.
7332 HashMem(reinterpret_cast<const unsigned char *>(key.data()),
289 7332 key.length(), &hash_key);
290 7332 memcpy(key_block, hash_key.digest, kDigestSizes[algorithm]);
291 } else {
292
2/2
✓ Branch 1 taken 600052 times.
✓ Branch 2 taken 3 times.
600055 if (key.length() > 0)
293 600052 memcpy(key_block, key.data(), key.length());
294 }
295
296 607387 unsigned char pad_block[block_size];
297 // Inner hash
298
1/2
✓ Branch 1 taken 607387 times.
✗ Branch 2 not taken.
607387 Any hash_inner(algorithm);
299
1/2
✓ Branch 1 taken 607387 times.
✗ Branch 2 not taken.
607387 ContextPtr context_inner(algorithm);
300 607387 context_inner.buffer = alloca(context_inner.size);
301
1/2
✓ Branch 1 taken 607387 times.
✗ Branch 2 not taken.
607387 Init(context_inner);
302
2/2
✓ Branch 0 taken 38872768 times.
✓ Branch 1 taken 607387 times.
39480155 for (unsigned i = 0; i < block_size; ++i)
303 38872768 pad_block[i] = key_block[i] ^ 0x36;
304
1/2
✓ Branch 1 taken 607387 times.
✗ Branch 2 not taken.
607387 Update(pad_block, block_size, context_inner);
305
1/2
✓ Branch 1 taken 607387 times.
✗ Branch 2 not taken.
607387 Update(buffer, buffer_size, context_inner);
306
1/2
✓ Branch 1 taken 607387 times.
✗ Branch 2 not taken.
607387 Final(context_inner, &hash_inner);
307
308 // Outer hash
309
1/2
✓ Branch 1 taken 607387 times.
✗ Branch 2 not taken.
607387 ContextPtr context_outer(algorithm);
310 607387 context_outer.buffer = alloca(context_outer.size);
311
1/2
✓ Branch 1 taken 607387 times.
✗ Branch 2 not taken.
607387 Init(context_outer);
312
2/2
✓ Branch 0 taken 38872768 times.
✓ Branch 1 taken 607387 times.
39480155 for (unsigned i = 0; i < block_size; ++i)
313 38872768 pad_block[i] = key_block[i] ^ 0x5c;
314
1/2
✓ Branch 1 taken 607387 times.
✗ Branch 2 not taken.
607387 Update(pad_block, block_size, context_outer);
315
1/2
✓ Branch 1 taken 607387 times.
✗ Branch 2 not taken.
607387 Update(hash_inner.digest, kDigestSizes[algorithm], context_outer);
316
317
1/2
✓ Branch 1 taken 607387 times.
✗ Branch 2 not taken.
607387 Final(context_outer, any_digest);
318 607387 }
319
320
321 11326 bool HashFd(int fd, Any *any_digest) {
322 11326 Algorithms algorithm = any_digest->algorithm;
323
1/2
✓ Branch 1 taken 11326 times.
✗ Branch 2 not taken.
11326 ContextPtr context(algorithm);
324 11326 context.buffer = alloca(context.size);
325
326
1/2
✓ Branch 1 taken 11326 times.
✗ Branch 2 not taken.
11326 Init(context);
327 unsigned char io_buffer[4096];
328 int actual_bytes;
329
3/4
✓ Branch 1 taken 4727548 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4716222 times.
✓ Branch 4 taken 11326 times.
4727548 while ((actual_bytes = read(fd, io_buffer, 4096)) != 0) {
330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4716222 times.
4716222 if (actual_bytes == -1) {
331 if (errno == EINTR)
332 continue;
333 return false;
334 }
335
1/2
✓ Branch 1 taken 4716222 times.
✗ Branch 2 not taken.
4716222 Update(io_buffer, actual_bytes, context);
336 }
337
1/2
✓ Branch 1 taken 11326 times.
✗ Branch 2 not taken.
11326 Final(context, any_digest);
338 11326 return true;
339 }
340
341
342 11326 bool HashFile(const std::string &filename, Any *any_digest) {
343 11326 int fd = open(filename.c_str(), O_RDONLY);
344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11326 times.
11326 if (fd == -1)
345 return false;
346
347 11326 bool result = HashFd(fd, any_digest);
348 11326 close(fd);
349 11326 return result;
350 }
351
352
353 /**
354 * Fast constructor for hashing path names.
355 */
356 6458 Md5::Md5(const AsciiPtr ascii) {
357 6458 algorithm = kMd5;
358 6458 const string *str = ascii.str;
359
360 MD5_CTX md5_state;
361
1/2
✓ Branch 1 taken 6458 times.
✗ Branch 2 not taken.
6458 MD5_Init(&md5_state);
362
1/2
✓ Branch 3 taken 6458 times.
✗ Branch 4 not taken.
6458 MD5_Update(&md5_state, reinterpret_cast<const unsigned char *>(&(*str)[0]),
363 str->length());
364
1/2
✓ Branch 1 taken 6458 times.
✗ Branch 2 not taken.
6458 MD5_Final(digest, &md5_state);
365 6458 }
366
367
368 1489538 Md5::Md5(const char *chars, const unsigned length) {
369 1489538 algorithm = kMd5;
370
371 MD5_CTX md5_state;
372
1/2
✓ Branch 1 taken 1489538 times.
✗ Branch 2 not taken.
1489538 MD5_Init(&md5_state);
373
1/2
✓ Branch 1 taken 1489538 times.
✗ Branch 2 not taken.
1489538 MD5_Update(&md5_state, reinterpret_cast<const unsigned char *>(chars),
374 length);
375
1/2
✓ Branch 1 taken 1489538 times.
✗ Branch 2 not taken.
1489538 MD5_Final(digest, &md5_state);
376 1489538 }
377
378
379 Md5::Md5(const uint64_t lo, const uint64_t hi) {
380 algorithm = kMd5;
381 memcpy(digest, &lo, 8);
382 memcpy(digest+8, &hi, 8);
383 }
384
385 8876 void Md5::ToIntPair(uint64_t *lo, uint64_t *hi) const {
386 8876 memcpy(lo, digest, 8);
387 8876 memcpy(hi, digest+8, 8);
388 8876 }
389
390
391 600068 Md5 Any::CastToMd5() {
392
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 600068 times.
600068 assert(algorithm == kMd5);
393 600068 Md5 result;
394 600068 memcpy(result.digest, digest, kDigestSizes[kMd5]);
395 600068 return result;
396 }
397
398 #ifndef OPENSSL_API_INTERFACE_V09
399 6 static string HexFromSha256(unsigned char digest[SHA256_DIGEST_LENGTH]) {
400 6 string result;
401
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 result.reserve(2 * SHA256_DIGEST_LENGTH);
402
2/2
✓ Branch 0 taken 192 times.
✓ Branch 1 taken 6 times.
198 for (unsigned i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
403 192 const char d1 = digest[i] / 16;
404 192 const char d2 = digest[i] % 16;
405
3/4
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 81 times.
✓ Branch 3 taken 192 times.
✗ Branch 4 not taken.
192 result.push_back(d1 + ((d1 <= 9) ? '0' : 'a' - 10));
406
3/4
✓ Branch 0 taken 133 times.
✓ Branch 1 taken 59 times.
✓ Branch 3 taken 192 times.
✗ Branch 4 not taken.
192 result.push_back(d2 + ((d2 <= 9) ? '0' : 'a' - 10));
407 }
408 6 return result;
409 }
410 #endif
411
412 1 string Sha256File(const string &filename) {
413 #ifdef OPENSSL_API_INTERFACE_V09
414 PANIC(NULL);
415 #else
416
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 int fd = open(filename.c_str(), O_RDONLY);
417
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (fd < 0)
418 return "";
419
420 SHA256_CTX ctx;
421
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 SHA256_Init(&ctx);
422
423 unsigned char io_buffer[4096];
424 int actual_bytes;
425
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 while ((actual_bytes = read(fd, io_buffer, 4096)) != 0) {
426 if (actual_bytes == -1) {
427 if (errno == EINTR)
428 continue;
429 close(fd);
430 return "";
431 }
432 SHA256_Update(&ctx, io_buffer, actual_bytes);
433 }
434
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 close(fd);
435
436 unsigned char digest[SHA256_DIGEST_LENGTH];
437
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 SHA256_Final(digest, &ctx);
438
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 return HexFromSha256(digest);
439 #endif
440 }
441
442 2 string Sha256Mem(const unsigned char *buffer, const unsigned buffer_size) {
443 #ifdef OPENSSL_API_INTERFACE_V09
444 PANIC(NULL);
445 #else
446 unsigned char digest[SHA256_DIGEST_LENGTH];
447
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 SHA256(buffer, buffer_size, digest);
448
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 return HexFromSha256(digest);
449 #endif
450 }
451
452 1 string Sha256String(const string &content) {
453 1 return Sha256Mem(reinterpret_cast<const unsigned char *>(content.data()),
454 1 content.length());
455 }
456
457
458 7 std::string Hmac256(
459 const std::string &key,
460 const std::string &content,
461 bool raw_output)
462 {
463 #ifdef OPENSSL_API_INTERFACE_V09
464 PANIC(NULL);
465 #else
466 unsigned char digest[SHA256_DIGEST_LENGTH];
467 7 const unsigned block_size = 64;
468 7 const unsigned key_length = key.length();
469 unsigned char key_block[block_size];
470 7 memset(key_block, 0, block_size);
471
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if (key_length > block_size) {
472
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 SHA256(reinterpret_cast<const unsigned char *>(key.data()), key_length,
473 key_block);
474 } else {
475
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 if (key.length() > 0)
476 6 memcpy(key_block, key.data(), key_length);
477 }
478
479 unsigned char pad_block[block_size];
480 // Inner hash
481 SHA256_CTX ctx_inner;
482 unsigned char digest_inner[SHA256_DIGEST_LENGTH];
483
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 SHA256_Init(&ctx_inner);
484
2/2
✓ Branch 0 taken 448 times.
✓ Branch 1 taken 7 times.
455 for (unsigned i = 0; i < block_size; ++i)
485 448 pad_block[i] = key_block[i] ^ 0x36;
486
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 SHA256_Update(&ctx_inner, pad_block, block_size);
487
1/2
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
7 SHA256_Update(&ctx_inner, content.data(), content.length());
488
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 SHA256_Final(digest_inner, &ctx_inner);
489
490 // Outer hash
491 SHA256_CTX ctx_outer;
492
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 SHA256_Init(&ctx_outer);
493
2/2
✓ Branch 0 taken 448 times.
✓ Branch 1 taken 7 times.
455 for (unsigned i = 0; i < block_size; ++i)
494 448 pad_block[i] = key_block[i] ^ 0x5c;
495
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 SHA256_Update(&ctx_outer, pad_block, block_size);
496
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 SHA256_Update(&ctx_outer, digest_inner, SHA256_DIGEST_LENGTH);
497
498
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 SHA256_Final(digest, &ctx_outer);
499
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 if (raw_output)
500
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 return string(reinterpret_cast<const char *>(digest), SHA256_DIGEST_LENGTH);
501
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 return HexFromSha256(digest);
502 #endif
503 }
504
505 } // namespace shash
506
507 #ifdef CVMFS_NAMESPACE_GUARD
508 } // namespace CVMFS_NAMESPACE_GUARD
509 #endif
510