GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/crypto/hash.cc
Date: 2024-04-21 02:33:16
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 #include "cvmfs_config.h"
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 132 bool HexPtr::IsValid() const {
38 132 const unsigned l = str->length();
39
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 126 times.
132 if (l == 0)
40 6 return false;
41 126 const char *c = str->data(); // Walks through the string
42 126 unsigned i = 0; // String position of *c
43
44
2/2
✓ Branch 0 taken 4920 times.
✓ Branch 1 taken 30 times.
4950 for ( ; i < l; ++i, ++c) {
45
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 4836 times.
4920 if (*c == '-')
46 84 break;
47
6/8
✓ Branch 0 taken 4836 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4836 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1962 times.
✓ Branch 5 taken 2874 times.
✓ Branch 6 taken 12 times.
✓ Branch 7 taken 1950 times.
4836 if ((*c < '0') || (*c > 'f') || ((*c > '9') && (*c < 'a')))
48 12 return false;
49 }
50
51 // Walk through all algorithms
52
2/2
✓ Branch 0 taken 420 times.
✓ Branch 1 taken 90 times.
510 for (unsigned j = 0; j < kAny; ++j) {
53 420 const unsigned hex_length = 2*kDigestSizes[j];
54 420 const unsigned algo_id_length = kAlgorithmIdSizes[j];
55
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 288 times.
420 if (i == hex_length) {
56 // Right suffix?
57
4/4
✓ Branch 0 taken 366 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 318 times.
✓ Branch 3 taken 48 times.
390 for ( ; (i < l) && (i-hex_length < algo_id_length); ++i, ++c) {
58
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 258 times.
318 if (*c != kAlgorithmIds[j][i-hex_length])
59 60 break;
60 }
61
3/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 108 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
132 if ((i == l) && (l == hex_length + algo_id_length))
62 24 return true;
63 108 i = hex_length;
64 108 c = str->data() + i;
65 }
66 }
67
68 90 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 5388 Any MkFromHexPtr(const HexPtr hex, const char suffix) {
84 5388 Any result;
85
86 5388 const unsigned length = hex.str->length();
87
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5382 times.
5388 if (length == 2*kDigestSizes[kMd5])
88 6 result = Any(kMd5, hex);
89
2/2
✓ Branch 0 taken 5188 times.
✓ Branch 1 taken 200 times.
5388 if (length == 2*kDigestSizes[kSha1])
90 5188 result = Any(kSha1, hex);
91 // TODO(jblomer) compare -rmd160, -shake128
92
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 5364 times.
5388 if ((length == 2*kDigestSizes[kRmd160] + kAlgorithmIdSizes[kRmd160]))
93 24 result = Any(kRmd160, hex);
94
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 5366 times.
5388 if ((length == 2*kDigestSizes[kShake128] + kAlgorithmIdSizes[kShake128]))
95 22 result = Any(kShake128, hex);
96
97 5388 result.suffix = suffix;
98 5388 return result;
99 }
100
101
102 /**
103 * Similar to MkFromHexPtr but the suffix is deducted from the HexPtr string.
104 */
105 41977 Any MkFromSuffixedHexPtr(const HexPtr hex) {
106 41977 Any result;
107
108 41977 const unsigned length = hex.str->length();
109
4/4
✓ Branch 0 taken 1381 times.
✓ Branch 1 taken 40596 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 1375 times.
41977 if ((length == 2*kDigestSizes[kMd5]) || (length == 2*kDigestSizes[kMd5] + 1))
110 {
111
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 40596 times.
40608 Suffix suffix = (length == 2*kDigestSizes[kMd5] + 1) ?
112 6 *(hex.str->rbegin()) : kSuffixNone;
113 40602 result = Any(kMd5, hex, suffix);
114 }
115
2/2
✓ Branch 0 taken 41238 times.
✓ Branch 1 taken 739 times.
41977 if ((length == 2*kDigestSizes[kSha1]) ||
116
2/2
✓ Branch 0 taken 594 times.
✓ Branch 1 taken 40644 times.
41238 (length == 2*kDigestSizes[kSha1] + 1))
117 {
118
2/2
✓ Branch 0 taken 594 times.
✓ Branch 1 taken 739 times.
1927 Suffix suffix = (length == 2*kDigestSizes[kSha1] + 1) ?
119 594 *(hex.str->rbegin()) : kSuffixNone;
120 1333 result = Any(kSha1, hex, suffix);
121 }
122
2/2
✓ Branch 0 taken 41971 times.
✓ Branch 1 taken 6 times.
41977 if ((length == 2*kDigestSizes[kRmd160] + kAlgorithmIdSizes[kRmd160]) ||
123
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 41953 times.
41971 (length == 2*kDigestSizes[kRmd160] + kAlgorithmIdSizes[kRmd160] + 1))
124 {
125 Suffix suffix =
126 24 (length == 2*kDigestSizes[kRmd160] + kAlgorithmIdSizes[kRmd160] + 1)
127
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 6 times.
24 ? *(hex.str->rbegin())
128 24 : kSuffixNone;
129 24 result = Any(kRmd160, hex, suffix);
130 }
131
2/2
✓ Branch 0 taken 41971 times.
✓ Branch 1 taken 6 times.
41977 if ((length == 2*kDigestSizes[kShake128] + kAlgorithmIdSizes[kShake128]) ||
132
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 41965 times.
41971 (length == 2*kDigestSizes[kShake128] + kAlgorithmIdSizes[kShake128] + 1))
133 {
134 Suffix suffix =
135 12 (length == 2*kDigestSizes[kShake128] + kAlgorithmIdSizes[kShake128] + 1)
136
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 ? *(hex.str->rbegin())
137 12 : kSuffixNone;
138 12 result = Any(kShake128, hex, suffix);
139 }
140
141 41977 return result;
142 }
143
144
145 /**
146 * Allows the caller to create the context on the stack.
147 */
148 2769923 unsigned GetContextSize(const Algorithms algorithm) {
149
4/5
✓ Branch 0 taken 1216522 times.
✓ Branch 1 taken 1552357 times.
✓ Branch 2 taken 74 times.
✓ Branch 3 taken 988 times.
✗ Branch 4 not taken.
2769923 switch (algorithm) {
150 1216522 case kMd5:
151 1216522 return sizeof(MD5_CTX);
152 1552357 case kSha1:
153 1552357 return sizeof(SHA_CTX);
154 74 case kRmd160:
155 74 return sizeof(RIPEMD160_CTX);
156 988 case kShake128:
157 988 return sizeof(Keccak_HashInstance);
158 default:
159 PANIC(kLogDebug | kLogSyslogErr,
160 "tried to generate hash context for unspecified hash. Aborting...");
161 }
162 }
163
164 2770193 void Init(ContextPtr context) {
165 HashReturn keccak_result;
166
4/5
✓ Branch 0 taken 1216540 times.
✓ Branch 1 taken 1552597 times.
✓ Branch 2 taken 74 times.
✓ Branch 3 taken 988 times.
✗ Branch 4 not taken.
2770193 switch (context.algorithm) {
167 1216540 case kMd5:
168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1216540 times.
1216540 assert(context.size == sizeof(MD5_CTX));
169 1216540 MD5_Init(reinterpret_cast<MD5_CTX *>(context.buffer));
170 1216540 break;
171 1552597 case kSha1:
172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1552597 times.
1552597 assert(context.size == sizeof(SHA_CTX));
173 1552597 SHA1_Init(reinterpret_cast<SHA_CTX *>(context.buffer));
174 1552579 break;
175 74 case kRmd160:
176
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 74 times.
74 assert(context.size == sizeof(RIPEMD160_CTX));
177 74 RIPEMD160_Init(reinterpret_cast<RIPEMD160_CTX *>(context.buffer));
178 74 break;
179 988 case kShake128:
180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 988 times.
988 assert(context.size == sizeof(Keccak_HashInstance));
181 988 keccak_result = Keccak_HashInitialize_SHAKE128(
182 reinterpret_cast<Keccak_HashInstance *>(context.buffer));
183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 988 times.
988 assert(keccak_result == SUCCESS);
184 988 break;
185 default:
186 PANIC(NULL); // Undefined hash
187 }
188 2770181 }
189
190 563235581 void Update(const unsigned char *buffer, const unsigned buffer_length,
191 ContextPtr context)
192 {
193 HashReturn keccak_result;
194
4/5
✓ Branch 0 taken 145331474 times.
✓ Branch 1 taken 141079011 times.
✓ Branch 2 taken 138412118 times.
✓ Branch 3 taken 138413002 times.
✗ Branch 4 not taken.
563235581 switch (context.algorithm) {
195 145331474 case kMd5:
196
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 145331474 times.
145331474 assert(context.size == sizeof(MD5_CTX));
197 145331474 MD5_Update(reinterpret_cast<MD5_CTX *>(context.buffer),
198 buffer, buffer_length);
199 145331474 break;
200 141079011 case kSha1:
201
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 141079011 times.
141079011 assert(context.size == sizeof(SHA_CTX));
202 141079011 SHA1_Update(reinterpret_cast<SHA_CTX *>(context.buffer),
203 buffer, buffer_length);
204 141085245 break;
205 138412118 case kRmd160:
206
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138412118 times.
138412118 assert(context.size == sizeof(RIPEMD160_CTX));
207 138412118 RIPEMD160_Update(reinterpret_cast<RIPEMD160_CTX *>(context.buffer),
208 buffer, buffer_length);
209 138412118 break;
210 138413002 case kShake128:
211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138413002 times.
138413002 assert(context.size == sizeof(Keccak_HashInstance));
212 276826004 keccak_result = Keccak_HashUpdate(reinterpret_cast<Keccak_HashInstance *>(
213 138413002 context.buffer), buffer, buffer_length * 8);
214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138413002 times.
138413002 assert(keccak_result == SUCCESS);
215 138413002 break;
216 default:
217 PANIC(NULL); // Undefined hash
218 }
219 563241839 }
220
221 2732833 void Final(ContextPtr context, Any *any_digest) {
222 HashReturn keccak_result;
223
4/5
✓ Branch 0 taken 1216516 times.
✓ Branch 1 taken 1515315 times.
✓ Branch 2 taken 74 times.
✓ Branch 3 taken 988 times.
✗ Branch 4 not taken.
2732833 switch (context.algorithm) {
224 1216516 case kMd5:
225
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1216516 times.
1216516 assert(context.size == sizeof(MD5_CTX));
226 1216516 MD5_Final(any_digest->digest,
227 1216516 reinterpret_cast<MD5_CTX *>(context.buffer));
228 1216516 break;
229 1515315 case kSha1:
230
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1515315 times.
1515315 assert(context.size == sizeof(SHA_CTX));
231 1515315 SHA1_Final(any_digest->digest,
232 1515315 reinterpret_cast<SHA_CTX *>(context.buffer));
233 1524321 break;
234 74 case kRmd160:
235
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 74 times.
74 assert(context.size == sizeof(RIPEMD160_CTX));
236 74 RIPEMD160_Final(any_digest->digest,
237 74 reinterpret_cast<RIPEMD160_CTX *>(context.buffer));
238 74 break;
239 988 case kShake128:
240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 988 times.
988 assert(context.size == sizeof(Keccak_HashInstance));
241 1976 keccak_result = Keccak_HashFinal(reinterpret_cast<Keccak_HashInstance *>(
242 988 context.buffer), NULL);
243
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 988 times.
988 assert(keccak_result == SUCCESS);
244 keccak_result =
245 1976 Keccak_HashSqueeze(reinterpret_cast<Keccak_HashInstance *>(
246 988 context.buffer), any_digest->digest, kDigestSizes[kShake128] * 8);
247 988 break;
248 default:
249 PANIC(NULL); // Undefined hash
250 }
251 2741899 any_digest->algorithm = context.algorithm;
252 2741899 }
253
254
255 15842 void HashMem(const unsigned char *buffer, const unsigned buffer_size,
256 Any *any_digest)
257 {
258 15842 Algorithms algorithm = any_digest->algorithm;
259
1/2
✓ Branch 1 taken 15842 times.
✗ Branch 2 not taken.
15842 ContextPtr context(algorithm);
260 15842 context.buffer = alloca(context.size);
261
262
1/2
✓ Branch 1 taken 15842 times.
✗ Branch 2 not taken.
15842 Init(context);
263
1/2
✓ Branch 1 taken 15842 times.
✗ Branch 2 not taken.
15842 Update(buffer, buffer_size, context);
264
1/2
✓ Branch 1 taken 15842 times.
✗ Branch 2 not taken.
15842 Final(context, any_digest);
265 15842 }
266
267
268 1274 void HashString(const std::string &content, Any *any_digest) {
269 1274 HashMem(reinterpret_cast<const unsigned char *>(content.data()),
270 1274 content.length(), any_digest);
271 1274 }
272
273
274 604990 void Hmac(
275 const string &key,
276 const unsigned char *buffer,
277 const unsigned buffer_size,
278 Any *any_digest
279 ) {
280 604990 Algorithms algorithm = any_digest->algorithm;
281
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 604990 times.
604990 assert(algorithm != kAny);
282
283 604990 const unsigned block_size = kBlockSizes[algorithm];
284 604990 unsigned char key_block[block_size];
285 604990 memset(key_block, 0, block_size);
286
2/2
✓ Branch 1 taken 4888 times.
✓ Branch 2 taken 600102 times.
604990 if (key.length() > block_size) {
287
1/2
✓ Branch 1 taken 4888 times.
✗ Branch 2 not taken.
4888 Any hash_key(algorithm);
288
1/2
✓ Branch 2 taken 4888 times.
✗ Branch 3 not taken.
4888 HashMem(reinterpret_cast<const unsigned char *>(key.data()),
289 4888 key.length(), &hash_key);
290 4888 memcpy(key_block, hash_key.digest, kDigestSizes[algorithm]);
291 } else {
292
2/2
✓ Branch 1 taken 600084 times.
✓ Branch 2 taken 18 times.
600102 if (key.length() > 0)
293 600084 memcpy(key_block, key.data(), key.length());
294 }
295
296 604990 unsigned char pad_block[block_size];
297 // Inner hash
298
1/2
✓ Branch 1 taken 604990 times.
✗ Branch 2 not taken.
604990 Any hash_inner(algorithm);
299
1/2
✓ Branch 1 taken 604990 times.
✗ Branch 2 not taken.
604990 ContextPtr context_inner(algorithm);
300 604990 context_inner.buffer = alloca(context_inner.size);
301
1/2
✓ Branch 1 taken 604990 times.
✗ Branch 2 not taken.
604990 Init(context_inner);
302
2/2
✓ Branch 0 taken 38719360 times.
✓ Branch 1 taken 604990 times.
39324350 for (unsigned i = 0; i < block_size; ++i)
303 38719360 pad_block[i] = key_block[i] ^ 0x36;
304
1/2
✓ Branch 1 taken 604990 times.
✗ Branch 2 not taken.
604990 Update(pad_block, block_size, context_inner);
305
1/2
✓ Branch 1 taken 604990 times.
✗ Branch 2 not taken.
604990 Update(buffer, buffer_size, context_inner);
306
1/2
✓ Branch 1 taken 604990 times.
✗ Branch 2 not taken.
604990 Final(context_inner, &hash_inner);
307
308 // Outer hash
309
1/2
✓ Branch 1 taken 604990 times.
✗ Branch 2 not taken.
604990 ContextPtr context_outer(algorithm);
310 604990 context_outer.buffer = alloca(context_outer.size);
311
1/2
✓ Branch 1 taken 604990 times.
✗ Branch 2 not taken.
604990 Init(context_outer);
312
2/2
✓ Branch 0 taken 38719360 times.
✓ Branch 1 taken 604990 times.
39324350 for (unsigned i = 0; i < block_size; ++i)
313 38719360 pad_block[i] = key_block[i] ^ 0x5c;
314
1/2
✓ Branch 1 taken 604990 times.
✗ Branch 2 not taken.
604990 Update(pad_block, block_size, context_outer);
315
1/2
✓ Branch 1 taken 604990 times.
✗ Branch 2 not taken.
604990 Update(hash_inner.digest, kDigestSizes[algorithm], context_outer);
316
317
1/2
✓ Branch 1 taken 604990 times.
✗ Branch 2 not taken.
604990 Final(context_outer, any_digest);
318 604990 }
319
320
321 11315 bool HashFd(int fd, Any *any_digest) {
322 11315 Algorithms algorithm = any_digest->algorithm;
323
1/2
✓ Branch 1 taken 11315 times.
✗ Branch 2 not taken.
11315 ContextPtr context(algorithm);
324 11315 context.buffer = alloca(context.size);
325
326
1/2
✓ Branch 1 taken 11315 times.
✗ Branch 2 not taken.
11315 Init(context);
327 unsigned char io_buffer[4096];
328 int actual_bytes;
329
3/4
✓ Branch 1 taken 4844235 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4832920 times.
✓ Branch 4 taken 11315 times.
4844235 while ((actual_bytes = read(fd, io_buffer, 4096)) != 0) {
330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4832920 times.
4832920 if (actual_bytes == -1) {
331 if (errno == EINTR)
332 continue;
333 return false;
334 }
335
1/2
✓ Branch 1 taken 4832920 times.
✗ Branch 2 not taken.
4832920 Update(io_buffer, actual_bytes, context);
336 }
337
1/2
✓ Branch 1 taken 11315 times.
✗ Branch 2 not taken.
11315 Final(context, any_digest);
338 11315 return true;
339 }
340
341
342 11315 bool HashFile(const std::string &filename, Any *any_digest) {
343 11315 int fd = open(filename.c_str(), O_RDONLY);
344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11315 times.
11315 if (fd == -1)
345 return false;
346
347 11315 bool result = HashFd(fd, any_digest);
348 11315 close(fd);
349 11315 return result;
350 }
351
352
353 /**
354 * Fast constructor for hashing path names.
355 */
356 7088 Md5::Md5(const AsciiPtr ascii) {
357 7088 algorithm = kMd5;
358 7088 const string *str = ascii.str;
359
360 MD5_CTX md5_state;
361
1/2
✓ Branch 1 taken 7088 times.
✗ Branch 2 not taken.
7088 MD5_Init(&md5_state);
362
1/2
✓ Branch 3 taken 7088 times.
✗ Branch 4 not taken.
7088 MD5_Update(&md5_state, reinterpret_cast<const unsigned char *>(&(*str)[0]),
363 str->length());
364
1/2
✓ Branch 1 taken 7088 times.
✗ Branch 2 not taken.
7088 MD5_Final(digest, &md5_state);
365 7088 }
366
367
368 1542618 Md5::Md5(const char *chars, const unsigned length) {
369 1542618 algorithm = kMd5;
370
371 MD5_CTX md5_state;
372
1/2
✓ Branch 1 taken 1542618 times.
✗ Branch 2 not taken.
1542618 MD5_Init(&md5_state);
373
1/2
✓ Branch 1 taken 1542618 times.
✗ Branch 2 not taken.
1542618 MD5_Update(&md5_state, reinterpret_cast<const unsigned char *>(chars),
374 length);
375
1/2
✓ Branch 1 taken 1542618 times.
✗ Branch 2 not taken.
1542618 MD5_Final(digest, &md5_state);
376 1542618 }
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 9336 void Md5::ToIntPair(uint64_t *lo, uint64_t *hi) const {
386 9336 memcpy(lo, digest, 8);
387 9336 memcpy(hi, digest+8, 8);
388 9336 }
389
390
391 600092 Md5 Any::CastToMd5() {
392
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 600092 times.
600092 assert(algorithm == kMd5);
393 600092 Md5 result;
394 600092 memcpy(result.digest, digest, kDigestSizes[kMd5]);
395 600092 return result;
396 }
397
398 #ifndef OPENSSL_API_INTERFACE_V09
399 36 static string HexFromSha256(unsigned char digest[SHA256_DIGEST_LENGTH]) {
400 36 string result;
401
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
36 result.reserve(2 * SHA256_DIGEST_LENGTH);
402
2/2
✓ Branch 0 taken 1152 times.
✓ Branch 1 taken 36 times.
1188 for (unsigned i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
403 1152 const char d1 = digest[i] / 16;
404 1152 const char d2 = digest[i] % 16;
405
3/4
✓ Branch 0 taken 666 times.
✓ Branch 1 taken 486 times.
✓ Branch 3 taken 1152 times.
✗ Branch 4 not taken.
1152 result.push_back(d1 + ((d1 <= 9) ? '0' : 'a' - 10));
406
3/4
✓ Branch 0 taken 798 times.
✓ Branch 1 taken 354 times.
✓ Branch 3 taken 1152 times.
✗ Branch 4 not taken.
1152 result.push_back(d2 + ((d2 <= 9) ? '0' : 'a' - 10));
407 }
408 36 return result;
409 }
410 #endif
411
412 6 string Sha256File(const string &filename) {
413 #ifdef OPENSSL_API_INTERFACE_V09
414 PANIC(NULL);
415 #else
416
1/2
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 int fd = open(filename.c_str(), O_RDONLY);
417
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (fd < 0)
418 return "";
419
420 SHA256_CTX ctx;
421
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 SHA256_Init(&ctx);
422
423 unsigned char io_buffer[4096];
424 int actual_bytes;
425
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
6 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 6 times.
✗ Branch 2 not taken.
6 close(fd);
435
436 unsigned char digest[SHA256_DIGEST_LENGTH];
437
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 SHA256_Final(digest, &ctx);
438
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 return HexFromSha256(digest);
439 #endif
440 }
441
442 12 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 12 times.
✗ Branch 2 not taken.
12 SHA256(buffer, buffer_size, digest);
448
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
24 return HexFromSha256(digest);
449 #endif
450 }
451
452 6 string Sha256String(const string &content) {
453 6 return Sha256Mem(reinterpret_cast<const unsigned char *>(content.data()),
454 6 content.length());
455 }
456
457
458 42 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 42 const unsigned block_size = 64;
468 42 const unsigned key_length = key.length();
469 unsigned char key_block[block_size];
470 42 memset(key_block, 0, block_size);
471
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 36 times.
42 if (key_length > block_size) {
472
1/2
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 SHA256(reinterpret_cast<const unsigned char *>(key.data()), key_length,
473 key_block);
474 } else {
475
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
36 if (key.length() > 0)
476 36 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 42 times.
✗ Branch 2 not taken.
42 SHA256_Init(&ctx_inner);
484
2/2
✓ Branch 0 taken 2688 times.
✓ Branch 1 taken 42 times.
2730 for (unsigned i = 0; i < block_size; ++i)
485 2688 pad_block[i] = key_block[i] ^ 0x36;
486
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
42 SHA256_Update(&ctx_inner, pad_block, block_size);
487
1/2
✓ Branch 3 taken 42 times.
✗ Branch 4 not taken.
42 SHA256_Update(&ctx_inner, content.data(), content.length());
488
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
42 SHA256_Final(digest_inner, &ctx_inner);
489
490 // Outer hash
491 SHA256_CTX ctx_outer;
492
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
42 SHA256_Init(&ctx_outer);
493
2/2
✓ Branch 0 taken 2688 times.
✓ Branch 1 taken 42 times.
2730 for (unsigned i = 0; i < block_size; ++i)
494 2688 pad_block[i] = key_block[i] ^ 0x5c;
495
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
42 SHA256_Update(&ctx_outer, pad_block, block_size);
496
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
42 SHA256_Update(&ctx_outer, digest_inner, SHA256_DIGEST_LENGTH);
497
498
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
42 SHA256_Final(digest, &ctx_outer);
499
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 18 times.
42 if (raw_output)
500
1/2
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
24 return string(reinterpret_cast<const char *>(digest), SHA256_DIGEST_LENGTH);
501
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 return HexFromSha256(digest);
502 #endif
503 }
504
505 } // namespace shash
506
507 #ifdef CVMFS_NAMESPACE_GUARD
508 } // namespace CVMFS_NAMESPACE_GUARD
509 #endif
510