GCC Code Coverage Report


Directory: src/
File: src/mpq-sha1.c
Date: 2026-10-06 13:47:41
Exec Total Coverage
Lines: 72 72 100.0%
Functions: 5 5 100.0%
Branches: 24 24 100.0%

Line Branch Exec Source
1 /*
2 * mpq-sha1.c -- private portable SHA-1 implementation.
3 *
4 * Copyright (c) 2003-2026 Maik Broemme <mbroemme@libmpq.org>
5 *
6 * This file is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
10 *
11 * This file is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this file; if not, see <https://www.gnu.org/licenses/>.
18 */
19
20 #include "mpq-sha1.h"
21 #include "mpq-endian.h"
22 #include <string.h>
23
24 static uint32_t
25 2360512 rotate_left(uint32_t value, unsigned int count)
26 {
27 2360512 return (value << count) | (value >> (32u - count));
28 }
29
30 static void
31 10538 transform(mpq_sha1_s *context, const uint8_t block[64])
32 {
33 uint32_t words[80];
34 10538 uint32_t a = context->state[0];
35 10538 uint32_t b = context->state[1];
36 10538 uint32_t c = context->state[2];
37 10538 uint32_t d = context->state[3];
38 10538 uint32_t e = context->state[4];
39 size_t i;
40
2/2
✓ Branch 0 taken 168608 times.
✓ Branch 1 taken 10538 times.
179146 for (i = 0; i < 16; ++i)
41 168608 words[i] = libmpq__load_be32(block + i * sizeof(uint32_t));
42
2/2
✓ Branch 0 taken 674432 times.
✓ Branch 1 taken 10538 times.
684970 for (; i < 80; ++i)
43 674432 words[i] = rotate_left(words[i - 3] ^ words[i - 8] ^ words[i - 14] ^ words[i - 16], 1);
44
2/2
✓ Branch 0 taken 843040 times.
✓ Branch 1 taken 10538 times.
853578 for (i = 0; i < 80; ++i) {
45 uint32_t f;
46 uint32_t k;
47 uint32_t next;
48
2/2
✓ Branch 0 taken 210760 times.
✓ Branch 1 taken 632280 times.
843040 if (i < 20) {
49 210760 f = (b & c) | ((~b) & d);
50 210760 k = 0x5a827999u;
51
2/2
✓ Branch 0 taken 210760 times.
✓ Branch 1 taken 421520 times.
632280 } else if (i < 40) {
52 210760 f = b ^ c ^ d;
53 210760 k = 0x6ed9eba1u;
54
2/2
✓ Branch 0 taken 210760 times.
✓ Branch 1 taken 210760 times.
421520 } else if (i < 60) {
55 210760 f = (b & c) | (b & d) | (c & d);
56 210760 k = 0x8f1bbcdcu;
57 } else {
58 210760 f = b ^ c ^ d;
59 210760 k = 0xca62c1d6u;
60 }
61 843040 next = rotate_left(a, 5) + f + e + k + words[i];
62 843040 e = d;
63 843040 d = c;
64 843040 c = rotate_left(b, 30);
65 843040 b = a;
66 843040 a = next;
67 }
68 10538 context->state[0] += a;
69 10538 context->state[1] += b;
70 10538 context->state[2] += c;
71 10538 context->state[3] += d;
72 10538 context->state[4] += e;
73 10538 memset(words, 0, sizeof(words));
74 10538 }
75
76 void
77 35 libmpq__sha1_init(mpq_sha1_s *context)
78 {
79 35 context->state[0] = 0x67452301u;
80 35 context->state[1] = 0xefcdab89u;
81 35 context->state[2] = 0x98badcfeu;
82 35 context->state[3] = 0x10325476u;
83 35 context->state[4] = 0xc3d2e1f0u;
84 35 context->bits = 0;
85 35 context->used = 0;
86 35 }
87
88 void
89 451 libmpq__sha1_update(mpq_sha1_s *context, const uint8_t *data, size_t size)
90 {
91 451 context->bits += (uint64_t)size * UINT64_C(8);
92
2/2
✓ Branch 0 taken 10896 times.
✓ Branch 1 taken 451 times.
11347 while (size != 0) {
93 10896 size_t count = sizeof(context->buffer) - context->used;
94
2/2
✓ Branch 0 taken 358 times.
✓ Branch 1 taken 10538 times.
10896 if (count > size)
95 358 count = size;
96 10896 memcpy(context->buffer + context->used, data, count);
97 10896 context->used += count;
98 10896 data += count;
99 10896 size -= count;
100
2/2
✓ Branch 0 taken 10538 times.
✓ Branch 1 taken 358 times.
10896 if (context->used == sizeof(context->buffer)) {
101 10538 transform(context, context->buffer);
102 10538 context->used = 0;
103 }
104 }
105 451 }
106
107 void
108 56 libmpq__sha1_final(mpq_sha1_s *context, uint8_t digest[LIBMPQ_SHA1_SIZE])
109 {
110 56 uint8_t padding[64] = { 0x80 };
111 uint8_t length[8];
112 56 uint64_t bits = context->bits;
113 size_t i;
114
2/2
✓ Branch 0 taken 448 times.
✓ Branch 1 taken 56 times.
504 for (i = 0; i < sizeof(length); ++i)
115 448 length[sizeof(length) - 1 - i] = (uint8_t)(bits >> (i * 8u));
116 56 libmpq__sha1_update(
117
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 3 times.
56 context, padding, context->used < 56 ? 56 - context->used : 120 - context->used
118 );
119 56 libmpq__sha1_update(context, length, sizeof(length));
120
2/2
✓ Branch 0 taken 280 times.
✓ Branch 1 taken 56 times.
336 for (i = 0; i < 5; ++i)
121 280 libmpq__store_be32(digest + i * sizeof(uint32_t), context->state[i]);
122 56 memset(context, 0, sizeof(*context));
123 56 }
124