| 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 |