aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/pubkey/xmss/xmss_tools.h
blob: e9f877eaedfe1e44636441ab1c4926fdd734d334 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
 * XMSS Tools
 * (C) 2016,2017 Matthias Gierlings
 *
 * Botan is released under the Simplified BSD License (see license.txt)
 **/

#ifndef BOTAN_XMSS_TOOLS_H_
#define BOTAN_XMSS_TOOLS_H_

#include <botan/cpuid.h>
#include <botan/secmem.h>
#include <iterator>
#include <type_traits>
#if defined(BOTAN_TARGET_OS_HAS_THREADS)
   #include <thread>
   #include <chrono>
   #include <botan/xmss_hash.h>
   #include <botan/auto_rng.h>
#endif

namespace Botan {

/**
 * Helper tools for low level byte operations required
 * for the XMSS implementation.
 **/
class XMSS_Tools final
   {
   public:
      XMSS_Tools(const XMSS_Tools&) = delete;
      void operator=(const XMSS_Tools&) = delete;

      /**
       * Concatenates the byte representation in big-endian order of any
       * integral value to a secure_vector.
       *
       * @param target Vector to concatenate the byte representation of the
       *               integral value to.
       * @param src integral value to concatenate.
       **/
      template<typename T,
               typename U = typename std::enable_if<std::is_integral<T>::value,
                     void>::type>
      static void concat(secure_vector<uint8_t>& target, const T& src);

      /**
       * Concatenates the last n bytes of the byte representation in big-endian
       * order of any integral value to a to a secure_vector.
       *
       * @param target Vector to concatenate the byte representation of the
       *               integral value to.
       * @param src Integral value to concatenate.
       * @param len number of bytes to concatenate. This value must be smaller
       *            or equal to the size of type T.
       **/
      template <typename T,
                typename U = typename std::enable_if<std::is_integral<T>::value,
                void>::type>
      static void concat(secure_vector<uint8_t>& target, const T& src, size_t len);

      /**
       * Not a public API function - will be removed in a future release.
       *
       * Determines the maximum number of threads to be used
       * efficiently, based on runtime timining measurements. Ideally the
       * result will correspond to the physical number of cores. On systems
       * supporting simultaneous multi threading (SMT)
       * std::thread::hardware_concurrency() usually reports a supported
       * number of threads which is bigger (typically by a factor of 2) than
       * the number of physical cores available. Using more threads than
       * physically available cores for computationally intesive tasks
       * resulted in slowdowns compared to using a number of threads equal to
       * the number of physical cores on test systems. This function is a
       * temporary workaround to prevent performance degradation due to
       * overstressing the CPU with too many threads.
       *
       * @return Presumed number of physical cores based on timing measurements.
       **/
      static size_t max_threads(); // TODO: Remove max_threads() and use
                                   // Botan::CPUID once proper plattform
                                   // independent detection of physical cores is
                                   // available.

   private:
      XMSS_Tools();
      /**
       * Measures the time t1 it takes to calculate hashes using
       * std::thread::hardware_concurrency() many threads and the time t2
       * calculating the same number of hashes using
       * std::thread::hardware_concurrency() / 2 threads.
       *
       * @return std::thread::hardware_concurrency() if t1 < t2
       *         std::thread::hardware_concurrency() / 2 otherwise.
       **/
      static size_t bench_threads(); // TODO: Remove bench_threads() and use
                                     // Botan::CPUID once proper plattform
                                     // independent detection of physical cores
                                     // is //available.
   };

template <typename T, typename U>
void XMSS_Tools::concat(secure_vector<uint8_t>& target, const T& src)
   {
   const uint8_t* src_bytes = reinterpret_cast<const uint8_t*>(&src);
   if(CPUID::is_little_endian())
      {
      std::reverse_copy(src_bytes,
                        src_bytes + sizeof(src),
                        std::back_inserter(target));
      }
   else
      {
      std::copy(src_bytes,
                src_bytes + sizeof(src),
                std::back_inserter(target));
      }
   }


template <typename T, typename U>
void XMSS_Tools::concat(secure_vector<uint8_t>& target,
                        const T& src,
                        size_t len)
   {
   size_t c = static_cast<size_t>(std::min(len, sizeof(src)));
   if(len > sizeof(src))
      {
      target.resize(target.size() + len - sizeof(src), 0);
      }

   const uint8_t* src_bytes = reinterpret_cast<const uint8_t*>(&src);
   if(CPUID::is_little_endian())
      {
      std::reverse_copy(src_bytes,
                        src_bytes + c,
                        std::back_inserter(target));
      }
   else
      {
      std::copy(src_bytes + sizeof(src) - c,
                src_bytes + sizeof(src),
                std::back_inserter(target));
      }
   }
}

#endif