• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 6253464532

19 Sep 2023 12:06AM UTC coverage: 91.748% (+0.02%) from 91.726%
6253464532

push

github

web-flow
Merge pull request #3693 from Rohde-Schwarz/refactor/alignment_buffer

Refactor: AlignmentBuffer<> helper for block-oriented Hashes

79472 of 86620 relevant lines covered (91.75%)

8492168.28 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.12
/src/lib/hash/skein/skein_512.cpp
1
/*
2
* The Skein-512 hash function
3
* (C) 2009,2010,2014 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include <botan/internal/skein_512.h>
9

10
#include <botan/exceptn.h>
11
#include <botan/internal/fmt.h>
12
#include <botan/internal/loadstor.h>
13
#include <botan/internal/stl_util.h>
14
#include <algorithm>
15

16
namespace Botan {
17

18
Skein_512::Skein_512(size_t arg_output_bits, std::string_view arg_personalization) :
4,123✔
19
      m_personalization(arg_personalization),
4,123✔
20
      m_output_bits(arg_output_bits),
4,123✔
21
      m_threefish(std::make_unique<Threefish_512>()),
4,123✔
22
      m_T(2) {
8,246✔
23
   if(m_output_bits == 0 || m_output_bits % 8 != 0 || m_output_bits > 512) {
4,123✔
24
      throw Invalid_Argument("Bad output bits size for Skein-512");
×
25
   }
26

27
   initial_block();
4,123✔
28
}
4,123✔
29

30
std::string Skein_512::name() const {
3,111✔
31
   if(m_personalization.empty()) {
3,111✔
32
      return fmt("Skein-512({})", m_output_bits);
3,108✔
33
   } else {
34
      return fmt("Skein-512({},{})", m_output_bits, m_personalization);
3✔
35
   }
36
}
37

38
std::unique_ptr<HashFunction> Skein_512::new_object() const {
1,037✔
39
   return std::make_unique<Skein_512>(m_output_bits, m_personalization);
1,037✔
40
}
41

42
std::unique_ptr<HashFunction> Skein_512::copy_state() const {
1,012✔
43
   auto copy = std::make_unique<Skein_512>(m_output_bits, m_personalization);
1,012✔
44
   copy->m_threefish->m_K = this->m_threefish->m_K;
1,012✔
45
   copy->m_T = this->m_T;
1,012✔
46
   copy->m_buffer = this->m_buffer;
1,012✔
47
   return copy;
1,012✔
48
}
1,012✔
49

50
void Skein_512::clear() {
1,037✔
51
   m_buffer.clear();
1,037✔
52

53
   initial_block();
1,037✔
54
}
1,037✔
55

56
void Skein_512::reset_tweak(type_code type, bool is_final) {
35,056✔
57
   m_T[0] = 0;
35,056✔
58

59
   m_T[1] =
35,056✔
60
      (static_cast<uint64_t>(type) << 56) | (static_cast<uint64_t>(1) << 62) | (static_cast<uint64_t>(is_final) << 63);
×
61
}
×
62

63
void Skein_512::initial_block() {
13,402✔
64
   const uint8_t zeros[64] = {0};
13,402✔
65

66
   m_threefish->set_key(zeros, sizeof(zeros));
13,402✔
67

68
   // ASCII("SHA3") followed by version (0x0001) code
69
   uint8_t config_str[32] = {0x53, 0x48, 0x41, 0x33, 0x01, 0x00, 0};
13,402✔
70
   store_le(uint32_t(m_output_bits), config_str + 8);
13,402✔
71

72
   reset_tweak(SKEIN_CONFIG, true);
13,402✔
73
   ubi_512(config_str, sizeof(config_str));
13,402✔
74

75
   if(!m_personalization.empty()) {
13,402✔
76
      /*
77
        This is a limitation of this implementation, and not of the
78
        algorithm specification. Could be fixed relatively easily, but
79
        doesn't seem worth the trouble.
80
      */
81
      if(m_personalization.length() > 64) {
10✔
82
         throw Invalid_Argument("Skein personalization must be less than 64 bytes");
×
83
      }
84

85
      const uint8_t* bits = cast_char_ptr_to_uint8(m_personalization.data());
10✔
86
      reset_tweak(SKEIN_PERSONALIZATION, true);
10✔
87
      ubi_512(bits, m_personalization.length());
10✔
88
   }
89

90
   reset_tweak(SKEIN_MSG, false);
13,402✔
91
}
13,402✔
92

93
void Skein_512::ubi_512(const uint8_t msg[], size_t msg_len) {
37,541✔
94
   secure_vector<uint64_t> M(8);
37,541✔
95

96
   do {
44,304✔
97
      const size_t to_proc = std::min<size_t>(msg_len, 64);
44,304✔
98
      m_T[0] += to_proc;
44,304✔
99

100
      load_le(M.data(), msg, to_proc / 8);
44,304✔
101

102
      if(to_proc % 8) {
44,304✔
103
         for(size_t j = 0; j != to_proc % 8; ++j) {
36,410✔
104
            M[to_proc / 8] |= static_cast<uint64_t>(msg[8 * (to_proc / 8) + j]) << (8 * j);
29,178✔
105
         }
106
      }
107

108
      m_threefish->skein_feedfwd(M, m_T);
44,304✔
109

110
      // clear first flag if set
111
      m_T[1] &= ~(static_cast<uint64_t>(1) << 62);
44,304✔
112

113
      msg_len -= to_proc;
44,304✔
114
      msg += to_proc;
44,304✔
115
   } while(msg_len);
44,304✔
116
}
37,541✔
117

118
void Skein_512::add_data(std::span<const uint8_t> input) {
18,869✔
119
   BufferSlicer in(input);
18,869✔
120

121
   while(!in.empty()) {
61,411✔
122
      if(const auto one_block = m_buffer.handle_unaligned_data(in)) {
23,673✔
123
         ubi_512(one_block->data(), one_block->size());
2,162✔
124
      }
125

126
      if(m_buffer.in_alignment()) {
23,673✔
127
         const auto [aligned_data, full_blocks] = m_buffer.aligned_data_to_process(in);
6,818✔
128
         if(full_blocks > 0) {
6,818✔
129
            ubi_512(aligned_data.data(), aligned_data.size());
5,483✔
130
         }
131
      }
132
   }
133
}
18,869✔
134

135
void Skein_512::final_result(std::span<uint8_t> out) {
8,242✔
136
   m_T[1] |= (static_cast<uint64_t>(1) << 63);  // final block flag
8,242✔
137

138
   const auto pos = m_buffer.elements_in_buffer();
8,242✔
139
   m_buffer.fill_up_with_zeros();
8,242✔
140
   ubi_512(m_buffer.consume().data(), pos);
8,242✔
141

142
   const uint8_t counter[8] = {0};
8,242✔
143

144
   reset_tweak(SKEIN_OUTPUT, true);
8,242✔
145
   ubi_512(counter, sizeof(counter));
8,242✔
146

147
   copy_out_vec_le(out.data(), m_output_bits / 8, m_threefish->m_K);
8,242✔
148

149
   initial_block();
8,242✔
150
}
8,242✔
151

152
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc