Repository: randombit/botan
Pull request #2717 (2021-04-17 00:12:51)

Make get_byte take a compile-time constant index
Add get_byte_var for the few cases that need a variable index


Patch:
diff --git a/src/lib/asn1/ber_dec.cpp b/src/lib/asn1/ber_dec.cpp
index 35872f54d..11f9b5412 100644
--- a/src/lib/asn1/ber_dec.cpp
+++ b/src/lib/asn1/ber_dec.cpp
@@ -96,7 +96,7 @@ size_t decode_length(DataSource* ber, size_t& field_size, size_t allow_indef)
 
    for(size_t i = 0; i != field_size - 1; ++i)
       {
-      if(get_byte(0, length) != 0)
+      if(get_byte<0>(length) != 0)
          throw BER_Decoding_Error("Field length overflow");
       if(!ber->read_byte(b))
          throw BER_Decoding_Error("Corrupted length field");
diff --git a/src/lib/asn1/der_enc.cpp b/src/lib/asn1/der_enc.cpp
index 8ae05b6a2..bdae43075 100644
--- a/src/lib/asn1/der_enc.cpp
+++ b/src/lib/asn1/der_enc.cpp
@@ -63,7 +63,7 @@ void encode_length(std::vector<uint8_t>& encoded_length, size_t length)
       encoded_length.push_back(static_cast<uint8_t>(0x80 | bytes_needed));
 
       for(size_t i = sizeof(length) - bytes_needed; i < sizeof(length); ++i)
-         encoded_length.push_back(get_byte(i, length));
+         encoded_length.push_back(get_byte_var(i, length));
       }
    }
 
diff --git a/src/lib/block/aria/aria.cpp b/src/lib/block/aria/aria.cpp
index 867ee7915..764dcf03c 100644
--- a/src/lib/block/aria/aria.cpp
+++ b/src/lib/block/aria/aria.cpp
@@ -138,10 +138,10 @@ inline uint32_t ARIA_F1(uint32_t X)
    const uint32_t M3 = 0x01010001;
    const uint32_t M4 = 0x01010100;
 
-   return (S1[get_byte(0, X)] * M1) ^
-          (S2[get_byte(1, X)] * M2) ^
-          (X1[get_byte(2, X)] * M3) ^
-          (X2[get_byte(3, X)] * M4);
+   return (S1[get_byte<0>(X)] * M1) ^
+          (S2[get_byte<1>(X)] * M2) ^
+          (X1[get_byte<2>(X)] * M3) ^
+          (X2[get_byte<3>(X)] * M4);
    }
 
 inline uint32_t ARIA_F2(uint32_t X)
@@ -151,10 +151,10 @@ inline uint32_t ARIA_F2(uint32_t X)
    const uint32_t M3 = 0x01010001;
    const uint32_t M4 = 0x01010100;
 
-   return (X1[get_byte(0, X)] * M3) ^
-          (X2[get_byte(1, X)] * M4) ^
-          (S1[get_byte(2, X)] * M1) ^
-          (S2[get_byte(3, X)] * M2);
+   return (X1[get_byte<0>(X)] * M3) ^
+          (X2[get_byte<1>(X)] * M4) ^
+          (S1[get_byte<2>(X)] * M1) ^
+          (S2[get_byte<3>(X)] * M2);
    }
 
 inline void ARIA_FO(uint32_t& T0, uint32_t& T1, uint32_t& T2, uint32_t& T3)
@@ -247,22 +247,22 @@ void transform(const uint8_t in[], uint8_t out[], size_t blocks,
             ARIA_FE(t0,t1,t2,t3);
          }
 
-      out[16*i+ 0] = X1[get_byte(0,t0)] ^ get_byte(0, KS[4*ROUNDS]);
-      out[16*i+ 1] = X2[get_byte(1,t0)] ^ get_byte(1, KS[4*ROUNDS]);
-      out[16*i+ 2] = S1[get_byte(2,t0)] ^ get_byte(2, KS[4*ROUNDS]);
-      out[16*i+ 3] = S2[get_byte(3,t0)] ^ get_byte(3, KS[4*ROUNDS]);
-      out[16*i+ 4] = X1[get_byte(0,t1)] ^ get_byte(0, KS[4*ROUNDS+1]);
-      out[16*i+ 5] = X2[get_byte(1,t1)] ^ get_byte(1, KS[4*ROUNDS+1]);
-      out[16*i+ 6] = S1[get_byte(2,t1)] ^ get_byte(2, KS[4*ROUNDS+1]);
-      out[16*i+ 7] = S2[get_byte(3,t1)] ^ get_byte(3, KS[4*ROUNDS+1]);
-      out[16*i+ 8] = X1[get_byte(0,t2)] ^ get_byte(0, KS[4*ROUNDS+2]);
-      out[16*i+ 9] = X2[get_byte(1,t2)] ^ get_byte(1, KS[4*ROUNDS+2]);
-      out[16*i+10] = S1[get_byte(2,t2)] ^ get_byte(2, KS[4*ROUNDS+2]);
-      out[16*i+11] = S2[get_byte(3,t2)] ^ get_byte(3, KS[4*ROUNDS+2]);
-      out[16*i+12] = X1[get_byte(0,t3)] ^ get_byte(0, KS[4*ROUNDS+3]);
-      out[16*i+13] = X2[get_byte(1,t3)] ^ get_byte(1, KS[4*ROUNDS+3]);
-      out[16*i+14] = S1[get_byte(2,t3)] ^ get_byte(2, KS[4*ROUNDS+3]);
-      out[16*i+15] = S2[get_byte(3,t3)] ^ get_byte(3, KS[4*ROUNDS+3]);
+      out[16*i+ 0] = X1[get_byte<0>(t0)] ^ get_byte<0>(KS[4*ROUNDS]);
+      out[16*i+ 1] = X2[get_byte<1>(t0)] ^ get_byte<1>(KS[4*ROUNDS]);
+      out[16*i+ 2] = S1[get_byte<2>(t0)] ^ get_byte<2>(KS[4*ROUNDS]);
+      out[16*i+ 3] = S2[get_byte<3>(t0)] ^ get_byte<3>(KS[4*ROUNDS]);
+      out[16*i+ 4] = X1[get_byte<0>(t1)] ^ get_byte<0>(KS[4*ROUNDS+1]);
+      out[16*i+ 5] = X2[get_byte<1>(t1)] ^ get_byte<1>(KS[4*ROUNDS+1]);
+      out[16*i+ 6] = S1[get_byte<2>(t1)] ^ get_byte<2>(KS[4*ROUNDS+1]);
+      out[16*i+ 7] = S2[get_byte<3>(t1)] ^ get_byte<3>(KS[4*ROUNDS+1]);
+      out[16*i+ 8] = X1[get_byte<0>(t2)] ^ get_byte<0>(KS[4*ROUNDS+2]);
+      out[16*i+ 9] = X2[get_byte<1>(t2)] ^ get_byte<1>(KS[4*ROUNDS+2]);
+      out[16*i+10] = S1[get_byte<2>(t2)] ^ get_byte<2>(KS[4*ROUNDS+2]);
+      out[16*i+11] = S2[get_byte<3>(t2)] ^ get_byte<3>(KS[4*ROUNDS+2]);
+      out[16*i+12] = X1[get_byte<0>(t3)] ^ get_byte<0>(KS[4*ROUNDS+3]);
+      out[16*i+13] = X2[get_byte<1>(t3)] ^ get_byte<1>(KS[4*ROUNDS+3]);
+      out[16*i+14] = S1[get_byte<2>(t3)] ^ get_byte<2>(KS[4*ROUNDS+3]);
+      out[16*i+15] = S2[get_byte<3>(t3)] ^ get_byte<3>(KS[4*ROUNDS+3]);
       }
    }
 
diff --git a/src/lib/block/blowfish/blowfish.cpp b/src/lib/block/blowfish/blowfish.cpp
index 70fed4132..70334f1a1 100644
--- a/src/lib/block/blowfish/blowfish.cpp
+++ b/src/lib/block/blowfish/blowfish.cpp
@@ -192,10 +192,10 @@ const uint32_t S_INIT[1024] = {
 
 inline uint32_t BFF(uint32_t X, const secure_vector<uint32_t>& S)
    {
-   const uint32_t s0 = S[get_byte(0, X)];
-   const uint32_t s1 = S[get_byte(1, X) + 256];
-   const uint32_t s2 = S[get_byte(2, X) + 512];
-   const uint32_t s3 = S[get_byte(3, X) + 768];
+   const uint32_t s0 = S[get_byte<0>(X)];
+   const uint32_t s1 = S[get_byte<1>(X) + 256];
+   const uint32_t s2 = S[get_byte<2>(X) + 512];
+   const uint32_t s3 = S[get_byte<3>(X) + 768];
 
    return (((s0 + s1) ^ s2) + s3);
    }
diff --git a/src/lib/block/camellia/camellia.cpp b/src/lib/block/camellia/camellia.cpp
index 8741e5475..2c1cc6be3 100644
--- a/src/lib/block/camellia/camellia.cpp
+++ b/src/lib/block/camellia/camellia.cpp
@@ -135,14 +135,14 @@ uint64_t F(uint64_t v, uint64_t K)
 
    const uint64_t x = v ^ K;
 
-   const uint64_t Z1 = M1 * SBOX1[get_byte(0, x)];
-   const uint64_t Z2 = M2 * SBOX2[get_byte(1, x)];
-   const uint64_t Z3 = M3 * SBOX3[get_byte(2, x)];
-   const uint64_t Z4 = M4 * SBOX4[get_byte(3, x)];
-   const uint64_t Z5 = M5 * SBOX2[get_byte(4, x)];
-   const uint64_t Z6 = M6 * SBOX3[get_byte(5, x)];
-   const uint64_t Z7 = M7 * SBOX4[get_byte(6, x)];
-   const uint64_t Z8 = M8 * SBOX1[get_byte(7, x)];
+   const uint64_t Z1 = M1 * SBOX1[get_byte<0>(x)];
+   const uint64_t Z2 = M2 * SBOX2[get_byte<1>(x)];
+   const uint64_t Z3 = M3 * SBOX3[get_byte<2>(x)];
+   const uint64_t Z4 = M4 * SBOX4[get_byte<3>(x)];
+   const uint64_t Z5 = M5 * SBOX2[get_byte<4>(x)];
+   const uint64_t Z6 = M6 * SBOX3[get_byte<5>(x)];
+   const uint64_t Z7 = M7 * SBOX4[get_byte<6>(x)];
+   const uint64_t Z8 = M8 * SBOX1[get_byte<7>(x)];
 
    return Z1 ^ Z2 ^ Z3 ^ Z4 ^ Z5 ^ Z6 ^ Z7 ^ Z8;
    }
diff --git a/src/lib/block/cast128/cast128.cpp b/src/lib/block/cast128/cast128.cpp
index 6f2941c67..7c778b9d3 100644
--- a/src/lib/block/cast128/cast128.cpp
+++ b/src/lib/block/cast128/cast128.cpp
@@ -199,8 +199,8 @@ alignas(256) const uint32_t CAST_SBOX4[256] = {
 inline uint32_t F1(uint32_t R, uint32_t MK, uint8_t RK)
    {
    const uint32_t T = rotl_var(MK + R, RK);
-   return (CAST_SBOX1[get_byte(0, T)] ^ CAST_SBOX2[get_byte(1, T)]) -
-           CAST_SBOX3[get_byte(2, T)] + CAST_SBOX4[get_byte(3, T)];
+   return (CAST_SBOX1[get_byte<0>(T)] ^ CAST_SBOX2[get_byte<1>(T)]) -
+           CAST_SBOX3[get_byte<2>(T)] + CAST_SBOX4[get_byte<3>(T)];
    }
 
 /*
@@ -209,8 +209,8 @@ inline uint32_t F1(uint32_t R, uint32_t MK, uint8_t RK)
 inline uint32_t F2(uint32_t R, uint32_t MK, uint8_t RK)
    {
    const uint32_t T = rotl_var(MK ^ R, RK);
-   return (CAST_SBOX1[get_byte(0, T)]  - CAST_SBOX2[get_byte(1, T)] +
-           CAST_SBOX3[get_byte(2, T)]) ^ CAST_SBOX4[get_byte(3, T)];
+   return (CAST_SBOX1[get_byte<0>(T)]  - CAST_SBOX2[get_byte<1>(T)] +
+           CAST_SBOX3[get_byte<2>(T)]) ^ CAST_SBOX4[get_byte<3>(T)];
    }
 
 /*
@@ -219,8 +219,8 @@ inline uint32_t F2(uint32_t R, uint32_t MK, uint8_t RK)
 inline uint32_t F3(uint32_t R, uint32_t MK, uint8_t RK)
    {
    const uint32_t T = rotl_var(MK - R, RK);
-   return ((CAST_SBOX1[get_byte(0, T)]  + CAST_SBOX2[get_byte(1, T)]) ^
-            CAST_SBOX3[get_byte(2, T)]) - CAST_SBOX4[get_byte(3, T)];
+   return ((CAST_SBOX1[get_byte<0>(T)]  + CAST_SBOX2[get_byte<1>(T)]) ^
+            CAST_SBOX3[get_byte<2>(T)]) - CAST_SBOX4[get_byte<3>(T)];
    }
 
 }
diff --git a/src/lib/block/gost_28147/gost_28147.cpp b/src/lib/block/gost_28147/gost_28147.cpp
index 12ff7cdf5..36c262086 100644
--- a/src/lib/block/gost_28147/gost_28147.cpp
+++ b/src/lib/block/gost_28147/gost_28147.cpp
@@ -96,16 +96,16 @@ std::string GOST_28147_89::name() const
 #define GOST_2ROUND(N1, N2, R1, R2)   \
    do {                               \
    uint32_t T0 = N1 + m_EK[R1];           \
-   N2 ^= m_SBOX[get_byte(3, T0)] |      \
-         m_SBOX[get_byte(2, T0)+256] |  \
-         m_SBOX[get_byte(1, T0)+512] |  \
-         m_SBOX[get_byte(0, T0)+768];   \
+   N2 ^= m_SBOX[get_byte<3>(T0)] |        \
+         m_SBOX[get_byte<2>(T0)+256] |       \
+         m_SBOX[get_byte<1>(T0)+512] |       \
+         m_SBOX[get_byte<0>(T0)+768];        \
                                       \
    uint32_t T1 = N2 + m_EK[R2];           \
-   N1 ^= m_SBOX[get_byte(3, T1)] |      \
-         m_SBOX[get_byte(2, T1)+256] |  \
-         m_SBOX[get_byte(1, T1)+512] |  \
-         m_SBOX[get_byte(0, T1)+768];   \
+   N1 ^= m_SBOX[get_byte<3>(T1)] |        \
+         m_SBOX[get_byte<2>(T1)+256] |       \
+         m_SBOX[get_byte<1>(T1)+512] |       \
+         m_SBOX[get_byte<0>(T1)+768];        \
    } while(0)
 
 /*
diff --git a/src/lib/block/seed/seed.cpp b/src/lib/block/seed/seed.cpp
index 5cfd6ac6d..0f28694c6 100644
--- a/src/lib/block/seed/seed.cpp
+++ b/src/lib/block/seed/seed.cpp
@@ -56,10 +56,10 @@ alignas(256) const uint8_t SEED_S1[256] = {
 inline uint32_t SEED_G(uint32_t X)
    {
    const uint32_t M = 0x01010101;
-   const uint32_t s0 = M * SEED_S0[get_byte(3, X)];
-   const uint32_t s1 = M * SEED_S1[get_byte(2, X)];
-   const uint32_t s2 = M * SEED_S0[get_byte(1, X)];
-   const uint32_t s3 = M * SEED_S1[get_byte(0, X)];
+   const uint32_t s0 = M * SEED_S0[get_byte<3>(X)];
+   const uint32_t s1 = M * SEED_S1[get_byte<2>(X)];
+   const uint32_t s2 = M * SEED_S0[get_byte<1>(X)];
+   const uint32_t s3 = M * SEED_S1[get_byte<0>(X)];
 
    const uint32_t M0 = 0x3FCFF3FC;
    const uint32_t M1 = 0xFC3FCFF3;
@@ -176,14 +176,14 @@ void SEED::key_schedule(const uint8_t key[], size_t)
       m_K[2*i+1] = SEED_G(WK[1] - WK[3] + RC[i]) ^ m_K[2*i];
 
       uint32_t T = (WK[0] & 0xFF) << 24;
-      WK[0] = (WK[0] >> 8) | (get_byte(3, WK[1]) << 24);
+      WK[0] = (WK[0] >> 8) | (get_byte<3>(WK[1]) << 24);
       WK[1] = (WK[1] >> 8) | T;
 
       m_K[2*i+2] = SEED_G(WK[0] + WK[2] - RC[i+1]);
       m_K[2*i+3] = SEED_G(WK[1] - WK[3] + RC[i+1]) ^ m_K[2*i+2];
 
-      T = get_byte(0, WK[3]);
-      WK[3] = (WK[3] << 8) | get_byte(0, WK[2]);
+      T = get_byte<0>(WK[3]);
+      WK[3] = (WK[3] << 8) | get_byte<0>(WK[2]);
       WK[2] = (WK[2] << 8) | T;
       }
    }
diff --git a/src/lib/block/sm4/sm4.cpp b/src/lib/block/sm4/sm4.cpp
index 3c0f419df..70bb41abf 100644
--- a/src/lib/block/sm4/sm4.cpp
+++ b/src/lib/block/sm4/sm4.cpp
@@ -84,10 +84,10 @@ alignas(256) const uint32_t SM4_SBOX_T[256] = {
 
 inline uint32_t SM4_T_slow(uint32_t b)
    {
-   const uint32_t t = make_uint32(SM4_SBOX[get_byte(0,b)],
-                                  SM4_SBOX[get_byte(1,b)],
-                                  SM4_SBOX[get_byte(2,b)],
-                                  SM4_SBOX[get_byte(3,b)]);
+   const uint32_t t = make_uint32(SM4_SBOX[get_byte<0>(b)],
+                                  SM4_SBOX[get_byte<1>(b)],
+                                  SM4_SBOX[get_byte<2>(b)],
+                                  SM4_SBOX[get_byte<3>(b)]);
 
    // L linear transform
    return t ^ rotl<2>(t) ^ rotl<10>(t) ^ rotl<18>(t) ^ rotl<24>(t);
@@ -95,19 +95,19 @@ inline uint32_t SM4_T_slow(uint32_t b)
 
 inline uint32_t SM4_T(uint32_t b)
    {
-   return          SM4_SBOX_T[get_byte(0,b)]  ^
-          rotr< 8>(SM4_SBOX_T[get_byte(1,b)]) ^
-          rotr<16>(SM4_SBOX_T[get_byte(2,b)]) ^
-          rotr<24>(SM4_SBOX_T[get_byte(3,b)]);
+   return          SM4_SBOX_T[get_byte<0>(b)]  ^
+      rotr< 8>(SM4_SBOX_T[get_byte<1>(b)]) ^
+      rotr<16>(SM4_SBOX_T[get_byte<2>(b)]) ^
+      rotr<24>(SM4_SBOX_T[get_byte<3>(b)]);
    }
 
 // Variant of T for key schedule
 inline uint32_t SM4_Tp(uint32_t b)
    {
-   const uint32_t t = make_uint32(SM4_SBOX[get_byte(0,b)],
-                                  SM4_SBOX[get_byte(1,b)],
-                                  SM4_SBOX[get_byte(2,b)],
-                                  SM4_SBOX[get_byte(3,b)]);
+   const uint32_t t = make_uint32(SM4_SBOX[get_byte<0>(b)],
+                                  SM4_SBOX[get_byte<1>(b)],
+                                  SM4_SBOX[get_byte<2>(b)],
+                                  SM4_SBOX[get_byte<3>(b)]);
 
    // L' linear transform
    return t ^ rotl<13>(t) ^ rotl<23>(t);
diff --git a/src/lib/block/twofish/twofish.cpp b/src/lib/block/twofish/twofish.cpp
index 7115aa689..dfb807c84 100644
--- a/src/lib/block/twofish/twofish.cpp
+++ b/src/lib/block/twofish/twofish.cpp
@@ -20,10 +20,10 @@ inline void TF_E(uint32_t A, uint32_t B, uint32_t& C, uint32_t& D,
                  uint32_t RK1, uint32_t RK2,
                  const secure_vector<uint32_t>& SB)
    {
-   uint32_t X = SB[    get_byte(3, A)] ^ SB[256+get_byte(2, A)] ^
-                SB[512+get_byte(1, A)] ^ SB[768+get_byte(0, A)];
-   uint32_t Y = SB[    get_byte(0, B)] ^ SB[256+get_byte(3, B)] ^
-                SB[512+get_byte(2, B)] ^ SB[768+get_byte(1, B)];
+   uint32_t X = SB[    get_byte<3>(A)] ^ SB[256+get_byte<2>(A)] ^
+                SB[512+get_byte<1>(A)] ^ SB[768+get_byte<0>(A)];
+   uint32_t Y = SB[    get_byte<0>(B)] ^ SB[256+get_byte<3>(B)] ^
+                SB[512+get_byte<2>(B)] ^ SB[768+get_byte<1>(B)];
 
    X += Y;
    Y += X;
@@ -39,10 +39,10 @@ inline void TF_D(uint32_t A, uint32_t B, uint32_t& C, uint32_t& D,
                  uint32_t RK1, uint32_t RK2,
                  const secure_vector<uint32_t>& SB)
    {
-   uint32_t X = SB[    get_byte(3, A)] ^ SB[256+get_byte(2, A)] ^
-                SB[512+get_byte(1, A)] ^ SB[768+get_byte(0, A)];
-   uint32_t Y = SB[    get_byte(0, B)] ^ SB[256+get_byte(3, B)] ^
-                SB[512+get_byte(2, B)] ^ SB[768+get_byte(1, B)];
+   uint32_t X = SB[    get_byte<3>(A)] ^ SB[256+get_byte<2>(A)] ^
+                SB[512+get_byte<1>(A)] ^ SB[768+get_byte<0>(A)];
+   uint32_t Y = SB[    get_byte<0>(B)] ^ SB[256+get_byte<3>(B)] ^
+                SB[512+get_byte<2>(B)] ^ SB[768+get_byte<1>(B)];
 
    X += Y;
    Y += X;
diff --git a/src/lib/hash/checksum/crc24/crc24.cpp b/src/lib/hash/checksum/crc24/crc24.cpp
index 4d1af3bd8..917f1db90 100644
--- a/src/lib/hash/checksum/crc24/crc24.cpp
+++ b/src/lib/hash/checksum/crc24/crc24.cpp
@@ -243,9 +243,9 @@ void CRC24::add_data(const uint8_t input[], size_t length)
 */
 void CRC24::final_result(uint8_t output[])
    {
-   output[0] = get_byte(3, m_crc);
-   output[1] = get_byte(2, m_crc);
-   output[2] = get_byte(1, m_crc);
+   output[0] = get_byte<3>(m_crc);
+   output[1] = get_byte<2>(m_crc);
+   output[2] = get_byte<1>(m_crc);
    clear();
    }
 
diff --git a/src/lib/hash/gost_3411/gost_3411.cpp b/src/lib/hash/gost_3411/gost_3411.cpp
index 22354d124..63dff2cb0 100644
--- a/src/lib/hash/gost_3411/gost_3411.cpp
+++ b/src/lib/hash/gost_3411/gost_3411.cpp
@@ -77,8 +77,8 @@ void GOST_34_11::compress_n(const uint8_t input[], size_t blocks)
       for(uint16_t j = 0, carry = 0; j != 32; ++j)
          {
          uint16_t s = m_sum[j] + input[32*i+j] + carry;
-         carry = get_byte(0, s);
-         m_sum[j] = get_byte(1, s);
+         carry = get_byte<0>(s);
+         m_sum[j] = get_byte<1>(s);
          }
 
       uint8_t S[32] = { 0 };
@@ -96,7 +96,7 @@ void GOST_34_11::compress_n(const uint8_t input[], size_t blocks)
             {
             const uint64_t UVk = U[k] ^ V[k];
             for(size_t l = 0; l != 8; ++l)
-               key[4*l+k] = get_byte(l, UVk);
+               key[4*l+k] = get_byte_var(l, UVk);
             }
 
          m_cipher.set_key(key, 32);
diff --git a/src/lib/hash/whirlpool/whirlpool.cpp b/src/lib/hash/whirlpool/whirlpool.cpp
index 6a6899d60..e1bebeb02 100644
--- a/src/lib/hash/whirlpool/whirlpool.cpp
+++ b/src/lib/hash/whirlpool/whirlpool.cpp
@@ -109,139 +109,139 @@ void Whirlpool::compress_n(const uint8_t in[], size_t blocks)
       for(size_t j = 0; j != 10; ++j)
          {
          uint64_t T0, T1, T2, T3, T4, T5, T6, T7;
-         T0 = WHIRL_S[get_byte(0, K0)] ^
-            rotr<8>(WHIRL_S[get_byte(1, K7)]) ^
-            rotr<16>(WHIRL_S[get_byte(2, K6)]) ^
-            rotr<24>(WHIRL_S[get_byte(3, K5)]) ^
-            rotr<32>(WHIRL_S[get_byte(4, K4)]) ^
-            rotr<40>(WHIRL_S[get_byte(5, K3)]) ^
-            rotr<48>(WHIRL_S[get_byte(6, K2)]) ^
-            rotr<56>(WHIRL_S[get_byte(7, K1)]) ^ RC[j];
+         T0 = WHIRL_S[get_byte<0>(K0)] ^
+            rotr<8>(WHIRL_S[get_byte<1>(K7)]) ^
+            rotr<16>(WHIRL_S[get_byte<2>(K6)]) ^
+            rotr<24>(WHIRL_S[get_byte<3>(K5)]) ^
+            rotr<32>(WHIRL_S[get_byte<4>(K4)]) ^
+            rotr<40>(WHIRL_S[get_byte<5>(K3)]) ^
+            rotr<48>(WHIRL_S[get_byte<6>(K2)]) ^
+            rotr<56>(WHIRL_S[get_byte<7>(K1)]) ^ RC[j];
 
-         T1 = WHIRL_S[get_byte(0, K1)] ^
-            rotr<8>(WHIRL_S[get_byte(1, K0)]) ^
-            rotr<16>(WHIRL_S[get_byte(2, K7)]) ^
-            rotr<24>(WHIRL_S[get_byte(3, K6)]) ^
-            rotr<32>(WHIRL_S[get_byte(4, K5)]) ^
-            rotr<40>(WHIRL_S[get_byte(5, K4)]) ^
-            rotr<48>(WHIRL_S[get_byte(6, K3)]) ^
-            rotr<56>(WHIRL_S[get_byte(7, K2)]);
-         T2 = WHIRL_S[get_byte(0, K2)] ^
-            rotr<8>(WHIRL_S[get_byte(1, K1)]) ^
-            rotr<16>(WHIRL_S[get_byte(2, K0)]) ^
-            rotr<24>(WHIRL_S[get_byte(3, K7)]) ^
-            rotr<32>(WHIRL_S[get_byte(4, K6)]) ^
-            rotr<40>(WHIRL_S[get_byte(5, K5)]) ^
-            rotr<48>(WHIRL_S[get_byte(6, K4)]) ^
-            rotr<56>(WHIRL_S[get_byte(7, K3)]);
-         T3 = WHIRL_S[get_byte(0, K3)] ^
-            rotr<8>(WHIRL_S[get_byte(1, K2)]) ^
-            rotr<16>(WHIRL_S[get_byte(2, K1)]) ^
-            rotr<24>(WHIRL_S[get_byte(3, K0)]) ^
-            rotr<32>(WHIRL_S[get_byte(4, K7)]) ^
-            rotr<40>(WHIRL_S[get_byte(5, K6)]) ^
-            rotr<48>(WHIRL_S[get_byte(6, K5)]) ^
-            rotr<56>(WHIRL_S[get_byte(7, K4)]);
-         T4 = WHIRL_S[get_byte(0, K4)] ^
-            rotr<8>(WHIRL_S[get_byte(1, K3)]) ^
-            rotr<16>(WHIRL_S[get_byte(2, K2)]) ^
-            rotr<24>(WHIRL_S[get_byte(3, K1)]) ^
-            rotr<32>(WHIRL_S[get_byte(4, K0)]) ^
-            rotr<40>(WHIRL_S[get_byte(5, K7)]) ^
-            rotr<48>(WHIRL_S[get_byte(6, K6)]) ^
-            rotr<56>(WHIRL_S[get_byte(7, K5)]);
-         T5 = WHIRL_S[get_byte(0, K5)] ^
-            rotr<8>(WHIRL_S[get_byte(1, K4)]) ^
-            rotr<16>(WHIRL_S[get_byte(2, K3)]) ^
-            rotr<24>(WHIRL_S[get_byte(3, K2)]) ^
-            rotr<32>(WHIRL_S[get_byte(4, K1)]) ^
-            rotr<40>(WHIRL_S[get_byte(5, K0)]) ^
-            rotr<48>(WHIRL_S[get_byte(6, K7)]) ^
-            rotr<56>(WHIRL_S[get_byte(7, K6)]);
-         T6 = WHIRL_S[get_byte(0, K6)] ^
-            rotr<8>(WHIRL_S[get_byte(1, K5)]) ^
-            rotr<16>(WHIRL_S[get_byte(2, K4)]) ^
-            rotr<24>(WHIRL_S[get_byte(3, K3)]) ^
-            rotr<32>(WHIRL_S[get_byte(4, K2)]) ^
-            rotr<40>(WHIRL_S[get_byte(5, K1)]) ^
-            rotr<48>(WHIRL_S[get_byte(6, K0)]) ^
-            rotr<56>(WHIRL_S[get_byte(7, K7)]);
-         T7 = WHIRL_S[get_byte(0, K7)] ^
-            rotr<8>(WHIRL_S[get_byte(1, K6)]) ^
-            rotr<16>(WHIRL_S[get_byte(2, K5)]) ^
-            rotr<24>(WHIRL_S[get_byte(3, K4)]) ^
-            rotr<32>(WHIRL_S[get_byte(4, K3)]) ^
-            rotr<40>(WHIRL_S[get_byte(5, K2)]) ^
-            rotr<48>(WHIRL_S[get_byte(6, K1)]) ^
-            rotr<56>(WHIRL_S[get_byte(7, K0)]);
+         T1 = WHIRL_S[get_byte<0>(K1)] ^
+            rotr<8>(WHIRL_S[get_byte<1>(K0)]) ^
+            rotr<16>(WHIRL_S[get_byte<2>(K7)]) ^
+            rotr<24>(WHIRL_S[get_byte<3>(K6)]) ^
+            rotr<32>(WHIRL_S[get_byte<4>(K5)]) ^
+            rotr<40>(WHIRL_S[get_byte<5>(K4)]) ^
+            rotr<48>(WHIRL_S[get_byte<6>(K3)]) ^
+            rotr<56>(WHIRL_S[get_byte<7>(K2)]);
+         T2 = WHIRL_S[get_byte<0>(K2)] ^
+            rotr<8>(WHIRL_S[get_byte<1>(K1)]) ^
+            rotr<16>(WHIRL_S[get_byte<2>(K0)]) ^
+            rotr<24>(WHIRL_S[get_byte<3>(K7)]) ^
+            rotr<32>(WHIRL_S[get_byte<4>(K6)]) ^
+            rotr<40>(WHIRL_S[get_byte<5>(K5)]) ^
+            rotr<48>(WHIRL_S[get_byte<6>(K4)]) ^
+            rotr<56>(WHIRL_S[get_byte<7>(K3)]);
+         T3 = WHIRL_S[get_byte<0>(K3)] ^
+            rotr<8>(WHIRL_S[get_byte<1>(K2)]) ^
+            rotr<16>(WHIRL_S[get_byte<2>(K1)]) ^
+            rotr<24>(WHIRL_S[get_byte<3>(K0)]) ^
+            rotr<32>(WHIRL_S[get_byte<4>(K7)]) ^
+            rotr<40>(WHIRL_S[get_byte<5>(K6)]) ^
+            rotr<48>(WHIRL_S[get_byte<6>(K5)]) ^
+            rotr<56>(WHIRL_S[get_byte<7>(K4)]);
+         T4 = WHIRL_S[get_byte<0>(K4)] ^
+            rotr<8>(WHIRL_S[get_byte<1>(K3)]) ^
+            rotr<16>(WHIRL_S[get_byte<2>(K2)]) ^
+            rotr<24>(WHIRL_S[get_byte<3>(K1)]) ^
+            rotr<32>(WHIRL_S[get_byte<4>(K0)]) ^
+            rotr<40>(WHIRL_S[get_byte<5>(K7)]) ^
+            rotr<48>(WHIRL_S[get_byte<6>(K6)]) ^
+            rotr<56>(WHIRL_S[get_byte<7>(K5)]);
+         T5 = WHIRL_S[get_byte<0>(K5)] ^
+            rotr<8>(WHIRL_S[get_byte<1>(K4)]) ^
+            rotr<16>(WHIRL_S[get_byte<2>(K3)]) ^
+            rotr<24>(WHIRL_S[get_byte<3>(K2)]) ^
+            rotr<32>(WHIRL_S[get_byte<4>(K1)]) ^
+            rotr<40>(WHIRL_S[get_byte<5>(K0)]) ^
+            rotr<48>(WHIRL_S[get_byte<6>(K7)]) ^
+            rotr<56>(WHIRL_S[get_byte<7>(K6)]);
+         T6 = WHIRL_S[get_byte<0>(K6)] ^
+            rotr<8>(WHIRL_S[get_byte<1>(K5)]) ^
+            rotr<16>(WHIRL_S[get_byte<2>(K4)]) ^
+            rotr<24>(WHIRL_S[get_byte<3>(K3)]) ^
+            rotr<32>(WHIRL_S[get_byte<4>(K2)]) ^
+            rotr<40>(WHIRL_S[get_byte<5>(K1)]) ^
+            rotr<48>(WHIRL_S[get_byte<6>(K0)]) ^
+            rotr<56>(WHIRL_S[get_byte<7>(K7)]);
+         T7 = WHIRL_S[get_byte<0>(K7)] ^
+            rotr<8>(WHIRL_S[get_byte<1>(K6)]) ^
+            rotr<16>(WHIRL_S[get_byte<2>(K5)]) ^
+            rotr<24>(WHIRL_S[get_byte<3>(K4)]) ^
+            rotr<32>(WHIRL_S[get_byte<4>(K3)]) ^
+            rotr<40>(WHIRL_S[get_byte<5>(K2)]) ^
+            rotr<48>(WHIRL_S[get_byte<6>(K1)]) ^
+            rotr<56>(WHIRL_S[get_byte<7>(K0)]);
 
          K0 = T0; K1 = T1; K2 = T2; K3 = T3;
          K4 = T4; K5 = T5; K6 = T6; K7 = T7;
 
-         T0 = WHIRL_S[get_byte(0, B0)] ^
-            rotr<8>(WHIRL_S[get_byte(1, B7)]) ^
-            rotr<16>(WHIRL_S[get_byte(2, B6)]) ^
-            rotr<24>(WHIRL_S[get_byte(3, B5)]) ^
-            rotr<32>(WHIRL_S[get_byte(4, B4)]) ^
-            rotr<40>(WHIRL_S[get_byte(5, B3)]) ^
-            rotr<48>(WHIRL_S[get_byte(6, B2)]) ^
-            rotr<56>(WHIRL_S[get_byte(7, B1)]) ^ K0;
-         T1 = WHIRL_S[get_byte(0, B1)] ^
-            rotr<8>(WHIRL_S[get_byte(1, B0)]) ^
-            rotr<16>(WHIRL_S[get_byte(2, B7)]) ^
-            rotr<24>(WHIRL_S[get_byte(3, B6)]) ^
-            rotr<32>(WHIRL_S[get_byte(4, B5)]) ^
-            rotr<40>(WHIRL_S[get_byte(5, B4)]) ^
-            rotr<48>(WHIRL_S[get_byte(6, B3)]) ^
-            rotr<56>(WHIRL_S[get_byte(7, B2)]) ^ K1;
-         T2 = WHIRL_S[get_byte(0, B2)] ^
-            rotr<8>(WHIRL_S[get_byte(1, B1)]) ^
-            rotr<16>(WHIRL_S[get_byte(2, B0)]) ^
-            rotr<24>(WHIRL_S[get_byte(3, B7)]) ^
-            rotr<32>(WHIRL_S[get_byte(4, B6)]) ^
-            rotr<40>(WHIRL_S[get_byte(5, B5)]) ^
-            rotr<48>(WHIRL_S[get_byte(6, B4)]) ^
-            rotr<56>(WHIRL_S[get_byte(7, B3)]) ^ K2;
-         T3 = WHIRL_S[get_byte(0, B3)] ^
-            rotr<8>(WHIRL_S[get_byte(1, B2)]) ^
-            rotr<16>(WHIRL_S[get_byte(2, B1)]) ^
-            rotr<24>(WHIRL_S[get_byte(3, B0)]) ^
-            rotr<32>(WHIRL_S[get_byte(4, B7)]) ^
-            rotr<40>(WHIRL_S[get_byte(5, B6)]) ^
-            rotr<48>(WHIRL_S[get_byte(6, B5)]) ^
-            rotr<56>(WHIRL_S[get_byte(7, B4)]) ^ K3;
-         T4 = WHIRL_S[get_byte(0, B4)] ^
-            rotr<8>(WHIRL_S[get_byte(1, B3)]) ^
-            rotr<16>(WHIRL_S[get_byte(2, B2)]) ^
-            rotr<24>(WHIRL_S[get_byte(3, B1)]) ^
-            rotr<32>(WHIRL_S[get_byte(4, B0)]) ^
-            rotr<40>(WHIRL_S[get_byte(5, B7)]) ^
-            rotr<48>(WHIRL_S[get_byte(6, B6)]) ^
-            rotr<56>(WHIRL_S[get_byte(7, B5)]) ^ K4;
-         T5 = WHIRL_S[get_byte(0, B5)] ^
-            rotr<8>(WHIRL_S[get_byte(1, B4)]) ^
-            rotr<16>(WHIRL_S[get_byte(2, B3)]) ^
-            rotr<24>(WHIRL_S[get_byte(3, B2)]) ^
-            rotr<32>(WHIRL_S[get_byte(4, B1)]) ^
-            rotr<40>(WHIRL_S[get_byte(5, B0)]) ^
-            rotr<48>(WHIRL_S[get_byte(6, B7)]) ^
-            rotr<56>(WHIRL_S[get_byte(7, B6)]) ^ K5;
-         T6 = WHIRL_S[get_byte(0, B6)] ^
-            rotr<8>(WHIRL_S[get_byte(1, B5)]) ^
-            rotr<16>(WHIRL_S[get_byte(2, B4)]) ^
-            rotr<24>(WHIRL_S[get_byte(3, B3)]) ^
-            rotr<32>(WHIRL_S[get_byte(4, B2)]) ^
-            rotr<40>(WHIRL_S[get_byte(5, B1)]) ^
-            rotr<48>(WHIRL_S[get_byte(6, B0)]) ^
-            rotr<56>(WHIRL_S[get_byte(7, B7)]) ^ K6;
-         T7 = WHIRL_S[get_byte(0, B7)] ^
-            rotr<8>(WHIRL_S[get_byte(1, B6)]) ^
-            rotr<16>(WHIRL_S[get_byte(2, B5)]) ^
-            rotr<24>(WHIRL_S[get_byte(3, B4)]) ^
-            rotr<32>(WHIRL_S[get_byte(4, B3)]) ^
-            rotr<40>(WHIRL_S[get_byte(5, B2)]) ^
-            rotr<48>(WHIRL_S[get_byte(6, B1)]) ^
-            rotr<56>(WHIRL_S[get_byte(7, B0)]) ^ K7;
+         T0 = WHIRL_S[get_byte<0>(B0)] ^
+            rotr<8>(WHIRL_S[get_byte<1>(B7)]) ^
+            rotr<16>(WHIRL_S[get_byte<2>(B6)]) ^
+            rotr<24>(WHIRL_S[get_byte<3>(B5)]) ^
+            rotr<32>(WHIRL_S[get_byte<4>(B4)]) ^
+            rotr<40>(WHIRL_S[get_byte<5>(B3)]) ^
+            rotr<48>(WHIRL_S[get_byte<6>(B2)]) ^
+            rotr<56>(WHIRL_S[get_byte<7>(B1)]) ^ K0;
+         T1 = WHIRL_S[get_byte<0>(B1)] ^
+            rotr<8>(WHIRL_S[get_byte<1>(B0)]) ^
+            rotr<16>(WHIRL_S[get_byte<2>(B7)]) ^
+            rotr<24>(WHIRL_S[get_byte<3>(B6)]) ^
+            rotr<32>(WHIRL_S[get_byte<4>(B5)]) ^
+            rotr<40>(WHIRL_S[get_byte<5>(B4)]) ^
+            rotr<48>(WHIRL_S[get_byte<6>(B3)]) ^
+            rotr<56>(WHIRL_S[get_byte<7>(B2)]) ^ K1;
+         T2 = WHIRL_S[get_byte<0>(B2)] ^
+            rotr<8>(WHIRL_S[get_byte<1>(B1)]) ^
+            rotr<16>(WHIRL_S[get_byte<2>(B0)]) ^
+            rotr<24>(WHIRL_S[get_byte<3>(B7)]) ^
+            rotr<32>(WHIRL_S[get_byte<4>(B6)]) ^
+            rotr<40>(WHIRL_S[get_byte<5>(B5)]) ^
+            rotr<48>(WHIRL_S[get_byte<6>(B4)]) ^
+            rotr<56>(WHIRL_S[get_byte<7>(B3)]) ^ K2;
+         T3 = WHIRL_S[get_byte<0>(B3)] ^
+            rotr<8>(WHIRL_S[get_byte<1>(B2)]) ^
+            rotr<16>(WHIRL_S[get_byte<2>(B1)]) ^
+            rotr<24>(WHIRL_S[get_byte<3>(B0)]) ^
+            rotr<32>(WHIRL_S[get_byte<4>(B7)]) ^
+            rotr<40>(WHIRL_S[get_byte<5>(B6)]) ^
+            rotr<48>(WHIRL_S[get_byte<6>(B5)]) ^
+            rotr<56>(WHIRL_S[get_byte<7>(B4)]) ^ K3;
+         T4 = WHIRL_S[get_byte<0>(B4)] ^
+            rotr<8>(WHIRL_S[get_byte<1>(B3)]) ^
+            rotr<16>(WHIRL_S[get_byte<2>(B2)]) ^
+            rotr<24>(WHIRL_S[get_byte<3>(B1)]) ^
+            rotr<32>(WHIRL_S[get_byte<4>(B0)]) ^
+            rotr<40>(WHIRL_S[get_byte<5>(B7)]) ^
+            rotr<48>(WHIRL_S[get_byte<6>(B6)]) ^
+            rotr<56>(WHIRL_S[get_byte<7>(B5)]) ^ K4;
+         T5 = WHIRL_S[get_byte<0>(B5)] ^
+            rotr<8>(WHIRL_S[get_byte<1>(B4)]) ^
+            rotr<16>(WHIRL_S[get_byte<2>(B3)]) ^
+            rotr<24>(WHIRL_S[get_byte<3>(B2)]) ^
+            rotr<32>(WHIRL_S[get_byte<4>(B1)]) ^
+            rotr<40>(WHIRL_S[get_byte<5>(B0)]) ^
+            rotr<48>(WHIRL_S[get_byte<6>(B7)]) ^
+            rotr<56>(WHIRL_S[get_byte<7>(B6)]) ^ K5;
+         T6 = WHIRL_S[get_byte<0>(B6)] ^
+            rotr<8>(WHIRL_S[get_byte<1>(B5)]) ^
+            rotr<16>(WHIRL_S[get_byte<2>(B4)]) ^
+            rotr<24>(WHIRL_S[get_byte<3>(B3)]) ^
+            rotr<32>(WHIRL_S[get_byte<4>(B2)]) ^
+            rotr<40>(WHIRL_S[get_byte<5>(B1)]) ^
+            rotr<48>(WHIRL_S[get_byte<6>(B0)]) ^
+            rotr<56>(WHIRL_S[get_byte<7>(B7)]) ^ K6;
+         T7 = WHIRL_S[get_byte<0>(B7)] ^
+            rotr<8>(WHIRL_S[get_byte<1>(B6)]) ^
+            rotr<16>(WHIRL_S[get_byte<2>(B5)]) ^
+            rotr<24>(WHIRL_S[get_byte<3>(B4)]) ^
+            rotr<32>(WHIRL_S[get_byte<4>(B3)]) ^
+            rotr<40>(WHIRL_S[get_byte<5>(B2)]) ^
+            rotr<48>(WHIRL_S[get_byte<6>(B1)]) ^
+            rotr<56>(WHIRL_S[get_byte<7>(B0)]) ^ K7;
 
          B0 = T0; B1 = T1; B2 = T2; B3 = T3;
          B4 = T4; B5 = T5; B6 = T6; B7 = T7;
diff --git a/src/lib/kdf/hkdf/hkdf.cpp b/src/lib/kdf/hkdf/hkdf.cpp
index fe39423b2..090cdefbc 100644
--- a/src/lib/kdf/hkdf/hkdf.cpp
+++ b/src/lib/kdf/hkdf/hkdf.cpp
@@ -112,8 +112,8 @@ hkdf_expand_label(const std::string& hash_fn,
    secure_vector<uint8_t> output(length16);
    std::vector<uint8_t> prefix(3 + label.size() + 1);
 
-   prefix[0] = get_byte(0, length16);
-   prefix[1] = get_byte(1, length16);
+   prefix[0] = get_byte<0>(length16);
+   prefix[1] = get_byte<1>(length16);
    prefix[2] = static_cast<uint8_t>(label.size());
 
    copy_mem(prefix.data() + 3,
diff --git a/src/lib/math/bigint/bigint.cpp b/src/lib/math/bigint/bigint.cpp
index 6a3923d55..33681f9e5 100644
--- a/src/lib/math/bigint/bigint.cpp
+++ b/src/lib/math/bigint/bigint.cpp
@@ -108,8 +108,8 @@ BigInt::BigInt(RandomNumberGenerator& rng, size_t bits, bool set_high_bit)
 
 uint8_t BigInt::byte_at(size_t n) const
    {
-   return get_byte(sizeof(word) - (n % sizeof(word)) - 1,
-                   word_at(n / sizeof(word)));
+   return get_byte_var(sizeof(word) - (n % sizeof(word)) - 1,
+                       word_at(n / sizeof(word)));
    }
 
 int32_t BigInt::cmp_word(word other) const
@@ -404,7 +404,7 @@ void BigInt::binary_encode(uint8_t output[], size_t len) const
 
       for(size_t i = 0; i != extra_bytes; ++i)
          {
-         output[extra_bytes - i - 1] = get_byte(sizeof(word) - i - 1, w);
+         output[extra_bytes - i - 1] = get_byte_var(sizeof(word) - i - 1, w);
          }
       }
    }
diff --git a/src/lib/misc/cryptobox/cryptobox.cpp b/src/lib/misc/cryptobox/cryptobox.cpp
index df2db5605..c566d074e 100644
--- a/src/lib/misc/cryptobox/cryptobox.cpp
+++ b/src/lib/misc/cryptobox/cryptobox.cpp
@@ -51,8 +51,7 @@ std::string encrypt(const uint8_t input[], size_t input_len,
       ciphertext
    */
    secure_vector<uint8_t> out_buf(CRYPTOBOX_HEADER_LEN + input_len);
-   for(size_t i = 0; i != VERSION_CODE_LEN; ++i)
-     out_buf[i] = get_byte(i, CRYPTOBOX_VERSION_CODE);
+   store_be(CRYPTOBOX_VERSION_CODE, out_buf.data());
    rng.randomize(&out_buf[VERSION_CODE_LEN], PBKDF_SALT_LEN);
    // space left for MAC here
    if(input_len > 0)
@@ -107,8 +106,11 @@ decrypt_bin(const uint8_t input[], size_t input_len,
       throw Decoding_Error("Invalid CryptoBox input");
 
    for(size_t i = 0; i != VERSION_CODE_LEN; ++i)
-      if(ciphertext[i] != get_byte(i, CRYPTOBOX_VERSION_CODE))
+      {
+      uint32_t version = load_be<uint32_t>(ciphertext.data(), 0);
+      if(version != CRYPTOBOX_VERSION_CODE)
          throw Decoding_Error("Bad CryptoBox version");
+      }
 
    const uint8_t* pbkdf_salt = &ciphertext[VERSION_CODE_LEN];
    const uint8_t* box_mac = &ciphertext[VERSION_CODE_LEN + PBKDF_SALT_LEN];
diff --git a/src/lib/misc/tss/tss.cpp b/src/lib/misc/tss/tss.cpp
index f027d3090..3c3a6de71 100644
--- a/src/lib/misc/tss/tss.cpp
+++ b/src/lib/misc/tss/tss.cpp
@@ -180,8 +180,8 @@ RTSS_Share::split(uint8_t M, uint8_t N,
    copy_mem(&share_header[0], identifier.data(), identifier.size());
    share_header[16] = hash_id;
    share_header[17] = M;
-   share_header[18] = get_byte(0, share_len);
-   share_header[19] = get_byte(1, share_len);
+   share_header[18] = get_byte<0>(share_len);
+   share_header[19] = get_byte<1>(share_len);
 
    // Create RTSS header in each share
    std::vector<RTSS_Share> shares(N);
diff --git a/src/lib/modes/aead/ccm/ccm.cpp b/src/lib/modes/aead/ccm/ccm.cpp
index 50f7118e7..5ae52eced 100644
--- a/src/lib/modes/aead/ccm/ccm.cpp
+++ b/src/lib/modes/aead/ccm/ccm.cpp
@@ -90,8 +90,8 @@ void CCM_Mode::set_associated_data(const uint8_t ad[], size_t length)
       // FIXME: support larger AD using length encoding rules
       BOTAN_ARG_CHECK(length < (0xFFFF - 0xFF), "Supported CCM AD length");
 
-      m_ad_buf.push_back(get_byte(0, static_cast<uint16_t>(length)));
-      m_ad_buf.push_back(get_byte(1, static_cast<uint16_t>(length)));
+      m_ad_buf.push_back(get_byte<0>(static_cast<uint16_t>(length)));
+      m_ad_buf.push_back(get_byte<1>(static_cast<uint16_t>(length)));
       m_ad_buf += std::make_pair(ad, length);
       while(m_ad_buf.size() % CCM_BS)
          m_ad_buf.push_back(0); // pad with zeros to full block size
@@ -121,7 +121,7 @@ void CCM_Mode::encode_length(uint64_t len, uint8_t out[])
    BOTAN_ASSERT_NOMSG(len_bytes >= 2 && len_bytes <= 8);
 
    for(size_t i = 0; i != len_bytes; ++i)
-      out[len_bytes-1-i] = get_byte(sizeof(uint64_t)-1-i, len);
+      out[len_bytes-1-i] = get_byte_var(sizeof(uint64_t)-1-i, len);
 
    if(len_bytes < 8 && (len >> (len_bytes*8)) > 0)
       throw Encoding_Error("CCM message length too long to encode in L field");
diff --git a/src/lib/passhash/passhash9/passhash9.cpp b/src/lib/passhash/passhash9/passhash9.cpp
index 337fad1fe..3681b7e1d 100644
--- a/src/lib/passhash/passhash9/passhash9.cpp
+++ b/src/lib/passhash/passhash9/passhash9.cpp
@@ -64,8 +64,8 @@ std::string generate_passhash9(const std::string& pass,
 
    secure_vector<uint8_t> blob;
    blob.push_back(alg_id);
-   blob.push_back(get_byte(0, work_factor));
-   blob.push_back(get_byte(1, work_factor));
+   blob.push_back(get_byte<0>(work_factor));
+   blob.push_back(get_byte<1>(work_factor));
    blob += salt;
    blob += kdf.derive_key(PASSHASH9_PBKDF_OUTPUT_LEN,
                           pass,
diff --git a/src/lib/pubkey/mce/mceliece_key.cpp b/src/lib/pubkey/mce/mceliece_key.cpp
index cfac93e3c..8c23bf659 100644
--- a/src/lib/pubkey/mce/mceliece_key.cpp
+++ b/src/lib/pubkey/mce/mceliece_key.cpp
@@ -144,17 +144,17 @@ secure_vector<uint8_t> McEliece_PrivateKey::private_key_bits() const
 
    for(uint16_t Linv : m_Linv)
       {
-      enc_support.push_back(get_byte(0, Linv));
-      enc_support.push_back(get_byte(1, Linv));
+      enc_support.push_back(get_byte<0>(Linv));
+      enc_support.push_back(get_byte<1>(Linv));
       }
    enc.encode(enc_support, ASN1_Type::OctetString);
    secure_vector<uint8_t> enc_H;
    for(uint32_t coef : m_coeffs)
       {
-      enc_H.push_back(get_byte(0, coef));
-      enc_H.push_back(get_byte(1, coef));
-      enc_H.push_back(get_byte(2, coef));
-      enc_H.push_back(get_byte(3, coef));
+      enc_H.push_back(get_byte<0>(coef));
+      enc_H.push_back(get_byte<1>(coef));
+      enc_H.push_back(get_byte<2>(coef));
+      enc_H.push_back(get_byte<3>(coef));
       }
    enc.encode(enc_H, ASN1_Type::OctetString);
    enc.end_cons();
diff --git a/src/lib/pubkey/mce/polyn_gf2m.cpp b/src/lib/pubkey/mce/polyn_gf2m.cpp
index dcaaa6a29..53b21d530 100644
--- a/src/lib/pubkey/mce/polyn_gf2m.cpp
+++ b/src/lib/pubkey/mce/polyn_gf2m.cpp
@@ -781,8 +781,8 @@ secure_vector<uint8_t> polyn_gf2m::encode() const
    for(unsigned i = 0; i < len; i++)
       {
       // "big endian" encoding of the GF(2^m) elements
-      result.push_back(get_byte(0, coeff[i]));
-      result.push_back(get_byte(1, coeff[i]));
+      result.push_back(get_byte<0>(coeff[i]));
+      result.push_back(get_byte<1>(coeff[i]));
       }
    return result;
    }
diff --git a/src/lib/pubkey/sm2/sm2.cpp b/src/lib/pubkey/sm2/sm2.cpp
index 51214a7e4..a25aa1516 100644
--- a/src/lib/pubkey/sm2/sm2.cpp
+++ b/src/lib/pubkey/sm2/sm2.cpp
@@ -64,8 +64,8 @@ std::vector<uint8_t> sm2_compute_za(HashFunction& hash,
 
    const uint16_t uid_len = static_cast<uint16_t>(8 * user_id.size());
 
-   hash.update(get_byte(0, uid_len));
-   hash.update(get_byte(1, uid_len));
+   hash.update(get_byte<0>(uid_len));
+   hash.update(get_byte<1>(uid_len));
    hash.update(user_id);
 
    const size_t p_bytes = domain.get_p_bytes();
diff --git a/src/lib/rng/processor_rng/processor_rng.cpp b/src/lib/rng/processor_rng/processor_rng.cpp
index ee54870f8..1dd786af9 100644
--- a/src/lib/rng/processor_rng/processor_rng.cpp
+++ b/src/lib/rng/processor_rng/processor_rng.cpp
@@ -132,8 +132,11 @@ void Processor_RNG::randomize(uint8_t out[], size_t out_len)
    if(out_len > 0) // at most sizeof(hwrng_output)-1
       {
       const hwrng_output r = read_hwrng();
+      uint8_t hwrng_bytes[sizeof(hwrng_output)];
+      store_le(r, hwrng_bytes);
+
       for(size_t i = 0; i != out_len; ++i)
-         out[i] = get_byte(i, r);
+         out[i] = hwrng_bytes[i];
       }
    }
 
diff --git a/src/lib/tls/msg_cert_status.cpp b/src/lib/tls/msg_cert_status.cpp
index ecc649a13..bccfa02da 100644
--- a/src/lib/tls/msg_cert_status.cpp
+++ b/src/lib/tls/msg_cert_status.cpp
@@ -60,7 +60,7 @@ std::vector<uint8_t> Certificate_Status::serialize() const
    std::vector<uint8_t> buf;
    buf.push_back(1); // type OCSP
    for(size_t i = 1; i < 4; ++i)
-      buf.push_back(get_byte(i, response_len));
+      buf.push_back(get_byte_var(i, response_len));
 
    buf += m_response;
    return buf;
diff --git a/src/lib/tls/msg_cert_verify.cpp b/src/lib/tls/msg_cert_verify.cpp
index 6fff19b59..3bc5bd76f 100644
--- a/src/lib/tls/msg_cert_verify.cpp
+++ b/src/lib/tls/msg_cert_verify.cpp
@@ -59,16 +59,16 @@ std::vector<uint8_t> Certificate_Verify::serialize() const
    if(m_scheme != Signature_Scheme::NONE)
       {
       const uint16_t scheme_code = static_cast<uint16_t>(m_scheme);
-      buf.push_back(get_byte(0, scheme_code));
-      buf.push_back(get_byte(1, scheme_code));
+      buf.push_back(get_byte<0>(scheme_code));
+      buf.push_back(get_byte<1>(scheme_code));
       }
 
    if(m_signature.size() > 0xFFFF)
       throw Encoding_Error("Certificate_Verify signature too long to encode");
 
    const uint16_t sig_len = static_cast<uint16_t>(m_signature.size());
-   buf.push_back(get_byte(0, sig_len));
-   buf.push_back(get_byte(1, sig_len));
+   buf.push_back(get_byte<0>(sig_len));
+   buf.push_back(get_byte<1>(sig_len));
    buf += m_signature;
 
    return buf;
diff --git a/src/lib/tls/msg_certificate.cpp b/src/lib/tls/msg_certificate.cpp
index f9a5856f9..b49ffeb3d 100644
--- a/src/lib/tls/msg_certificate.cpp
+++ b/src/lib/tls/msg_certificate.cpp
@@ -92,14 +92,14 @@ std::vector<uint8_t> Certificate::serialize() const
       const size_t cert_size = raw_cert.size();
       for(size_t j = 0; j != 3; ++j)
          {
-         buf.push_back(get_byte(j+1, static_cast<uint32_t>(cert_size)));
+         buf.push_back(get_byte_var(j+1, static_cast<uint32_t>(cert_size)));
          }
       buf += raw_cert;
       }
 
    const size_t buf_size = buf.size() - 3;
    for(size_t i = 0; i != 3; ++i)
-      buf[i] = get_byte(i+1, static_cast<uint32_t>(buf_size));
+      buf[i] = get_byte_var(i+1, static_cast<uint32_t>(buf_size));
 
    return buf;
    }
diff --git a/src/lib/tls/msg_server_hello.cpp b/src/lib/tls/msg_server_hello.cpp
index 527352e78..7bce3d2c3 100644
--- a/src/lib/tls/msg_server_hello.cpp
+++ b/src/lib/tls/msg_server_hello.cpp
@@ -192,8 +192,8 @@ std::vector<uint8_t> Server_Hello::serialize() const
 
    append_tls_length_value(buf, m_session_id, 1);
 
-   buf.push_back(get_byte(0, m_ciphersuite));
-   buf.push_back(get_byte(1, m_ciphersuite));
+   buf.push_back(get_byte<0>(m_ciphersuite));
+   buf.push_back(get_byte<1>(m_ciphersuite));
 
    buf.push_back(m_comp_method);
 
diff --git a/src/lib/tls/msg_server_kex.cpp b/src/lib/tls/msg_server_kex.cpp
index 54f341e5b..f022d953d 100644
--- a/src/lib/tls/msg_server_kex.cpp
+++ b/src/lib/tls/msg_server_kex.cpp
@@ -128,8 +128,8 @@ Server_Key_Exchange::Server_Key_Exchange(Handshake_IO& io,
 
       const uint16_t named_curve_id = static_cast<uint16_t>(shared_group);
       m_params.push_back(3); // named curve
-      m_params.push_back(get_byte(0, named_curve_id));
-      m_params.push_back(get_byte(1, named_curve_id));
+      m_params.push_back(get_byte<0>(named_curve_id));
+      m_params.push_back(get_byte<1>(named_curve_id));
 
       append_tls_length_value(m_params, ecdh_public_val, 1);
       }
@@ -237,8 +237,8 @@ std::vector<uint8_t> Server_Key_Exchange::serialize() const
       if(m_scheme != Signature_Scheme::NONE)
          {
          const uint16_t scheme_code = static_cast<uint16_t>(m_scheme);
-         buf.push_back(get_byte(0, scheme_code));
-         buf.push_back(get_byte(1, scheme_code));
+         buf.push_back(get_byte<0>(scheme_code));
+         buf.push_back(get_byte<1>(scheme_code));
          }
 
       append_tls_length_value(buf, m_signature, 2);
diff --git a/src/lib/tls/tls_cbc/tls_cbc.cpp b/src/lib/tls/tls_cbc/tls_cbc.cpp
index 70a181c7c..72ea7737e 100644
--- a/src/lib/tls/tls_cbc/tls_cbc.cpp
+++ b/src/lib/tls/tls_cbc/tls_cbc.cpp
@@ -125,8 +125,8 @@ std::vector<uint8_t> TLS_CBC_HMAC_AEAD_Mode::assoc_data_with_len(uint16_t len)
    {
    std::vector<uint8_t> ad = m_ad;
    BOTAN_ASSERT(ad.size() == 13, "Expected AAD size");
-   ad[11] = get_byte(0, len);
-   ad[12] = get_byte(1, len);
+   ad[11] = get_byte<0>(len);
+   ad[12] = get_byte<1>(len);
    return ad;
    }
 
@@ -147,8 +147,8 @@ void TLS_CBC_HMAC_AEAD_Encryption::set_associated_data(const uint8_t ad[], size_
       // EtM uses ciphertext size instead of plaintext size for AEAD input
       const uint16_t pt_size = make_uint16(assoc_data()[11], assoc_data()[12]);
       const uint16_t enc_size = static_cast<uint16_t>(round_up(iv_size() + pt_size + 1, block_size()));
-      assoc_data()[11] = get_byte<uint16_t>(0, enc_size);
-      assoc_data()[12] = get_byte<uint16_t>(1, enc_size);
+      assoc_data()[11] = get_byte<0, uint16_t>(enc_size);
+      assoc_data()[12] = get_byte<1, uint16_t>(enc_size);
       }
    }
 
diff --git a/src/lib/tls/tls_channel.cpp b/src/lib/tls/tls_channel.cpp
index e41f7a254..bdf124767 100644
--- a/src/lib/tls/tls_channel.cpp
+++ b/src/lib/tls/tls_channel.cpp
@@ -711,8 +711,8 @@ SymmetricKey Channel::key_material_export(const std::string& label,
          size_t context_size = context.length();
          if(context_size > 0xFFFF)
             throw Invalid_Argument("key_material_export context is too long");
-         salt.push_back(get_byte(0, static_cast<uint16_t>(context_size)));
-         salt.push_back(get_byte(1, static_cast<uint16_t>(context_size)));
+         salt.push_back(get_byte<0>(static_cast<uint16_t>(context_size)));
+         salt.push_back(get_byte<1>(static_cast<uint16_t>(context_size)));
          salt += to_byte_vector(context);
          }
 
diff --git a/src/lib/tls/tls_extensions.cpp b/src/lib/tls/tls_extensions.cpp
index 745350b32..792ebb5fc 100644
--- a/src/lib/tls/tls_extensions.cpp
+++ b/src/lib/tls/tls_extensions.cpp
@@ -102,19 +102,19 @@ std::vector<uint8_t> Extensions::serialize(Connection_Side whoami) const
 
       const std::vector<uint8_t> extn_val = extn.second->serialize(whoami);
 
-      buf.push_back(get_byte(0, extn_code));
-      buf.push_back(get_byte(1, extn_code));
+      buf.push_back(get_byte<0>(extn_code));
+      buf.push_back(get_byte<1>(extn_code));
 
-      buf.push_back(get_byte(0, static_cast<uint16_t>(extn_val.size())));
-      buf.push_back(get_byte(1, static_cast<uint16_t>(extn_val.size())));
+      buf.push_back(get_byte<0>(static_cast<uint16_t>(extn_val.size())));
+      buf.push_back(get_byte<1>(static_cast<uint16_t>(extn_val.size())));
 
       buf += extn_val;
       }
 
    const uint16_t extn_size = static_cast<uint16_t>(buf.size() - 2);
 
-   buf[0] = get_byte(0, extn_size);
-   buf[1] = get_byte(1, extn_size);
+   buf[0] = get_byte<0>(extn_size);
+   buf[1] = get_byte<1>(extn_size);
 
    // avoid sending a completely empty extensions block
    if(buf.size() == 2)
@@ -191,12 +191,12 @@ std::vector<uint8_t> Server_Name_Indicator::serialize(Connection_Side /*whoami*/
 
    size_t name_len = m_sni_host_name.size();
 
-   buf.push_back(get_byte(0, static_cast<uint16_t>(name_len+3)));
-   buf.push_back(get_byte(1, static_cast<uint16_t>(name_len+3)));
+   buf.push_back(get_byte<0>(static_cast<uint16_t>(name_len+3)));
+   buf.push_back(get_byte<1>(static_cast<uint16_t>(name_len+3)));
    buf.push_back(0); // DNS
 
-   buf.push_back(get_byte(0, static_cast<uint16_t>(name_len)));
-   buf.push_back(get_byte(1, static_cast<uint16_t>(name_len)));
+   buf.push_back(get_byte<0>(static_cast<uint16_t>(name_len)));
+   buf.push_back(get_byte<1>(static_cast<uint16_t>(name_len)));
 
    buf += std::make_pair(
       cast_char_ptr_to_uint8(m_sni_host_name.data()),
@@ -272,8 +272,8 @@ std::vector<uint8_t> Application_Layer_Protocol_Notification::serialize(Connecti
                                  1);
       }
 
-   buf[0] = get_byte(0, static_cast<uint16_t>(buf.size()-2));
-   buf[1] = get_byte(1, static_cast<uint16_t>(buf.size()-2));
+   buf[0] = get_byte<0>(static_cast<uint16_t>(buf.size()-2));
+   buf[1] = get_byte<1>(static_cast<uint16_t>(buf.size()-2));
 
    return buf;
    }
@@ -314,13 +314,13 @@ std::vector<uint8_t> Supported_Groups::serialize(Connection_Side /*whoami*/) con
 
       if(id > 0)
          {
-         buf.push_back(get_byte(0, id));
-         buf.push_back(get_byte(1, id));
+         buf.push_back(get_byte<0>(id));
+         buf.push_back(get_byte<1>(id));
          }
       }
 
-   buf[0] = get_byte(0, static_cast<uint16_t>(buf.size()-2));
-   buf[1] = get_byte(1, static_cast<uint16_t>(buf.size()-2));
+   buf[0] = get_byte<0>(static_cast<uint16_t>(buf.size()-2));
+   buf[1] = get_byte<1>(static_cast<uint16_t>(buf.size()-2));
 
    return buf;
    }
@@ -395,15 +395,15 @@ std::vector<uint8_t> Signature_Algorithms::serialize(Connection_Side /*whoami*/)
 
    const uint16_t len = static_cast<uint16_t>(m_schemes.size() * 2);
 
-   buf.push_back(get_byte(0, len));
-   buf.push_back(get_byte(1, len));
+   buf.push_back(get_byte<0>(len));
+   buf.push_back(get_byte<1>(len));
 
    for(Signature_Scheme scheme : m_schemes)
       {
       const uint16_t scheme_code = static_cast<uint16_t>(scheme);
 
-      buf.push_back(get_byte(0, scheme_code));
-      buf.push_back(get_byte(1, scheme_code));
+      buf.push_back(get_byte<0>(scheme_code));
+      buf.push_back(get_byte<1>(scheme_code));
       }
 
    return buf;
@@ -448,13 +448,13 @@ std::vector<uint8_t> SRTP_Protection_Profiles::serialize(Connection_Side /*whoam
    std::vector<uint8_t> buf;
 
    const uint16_t pp_len = static_cast<uint16_t>(m_pp.size() * 2);
-   buf.push_back(get_byte(0, pp_len));
-   buf.push_back(get_byte(1, pp_len));
+   buf.push_back(get_byte<0>(pp_len));
+   buf.push_back(get_byte<1>(pp_len));
 
    for(uint16_t pp : m_pp)
       {
-      buf.push_back(get_byte(0, pp));
-      buf.push_back(get_byte(1, pp));
+      buf.push_back(get_byte<0>(pp));
+      buf.push_back(get_byte<1>(pp));
       }
 
    buf.push_back(0); // srtp_mki, always empty here
@@ -564,8 +564,8 @@ std::vector<uint8_t> Supported_Versions::serialize(Connection_Side whoami) const
 
       for(Protocol_Version version : m_versions)
          {
-         buf.push_back(get_byte(0, version.major_version()));
-         buf.push_back(get_byte(1, version.minor_version()));
+         buf.push_back(version.major_version());
+         buf.push_back(version.minor_version());
          }
       }
 
diff --git a/src/lib/tls/tls_handshake_io.cpp b/src/lib/tls/tls_handshake_io.cpp
index 28a3254b9..04dc1fe49 100644
--- a/src/lib/tls/tls_handshake_io.cpp
+++ b/src/lib/tls/tls_handshake_io.cpp
@@ -29,9 +29,9 @@ inline size_t load_be24(const uint8_t q[3])
 
 void store_be24(uint8_t out[3], size_t val)
    {
-   out[0] = get_byte(1, static_cast<uint32_t>(val));
-   out[1] = get_byte(2, static_cast<uint32_t>(val));
-   out[2] = get_byte(3, static_cast<uint32_t>(val));
+   out[0] = get_byte<1>(static_cast<uint32_t>(val));
+   out[1] = get_byte<2>(static_cast<uint32_t>(val));
+   out[2] = get_byte<3>(static_cast<uint32_t>(val));
    }
 
 uint64_t steady_clock_ms()
diff --git a/src/lib/tls/tls_reader.h b/src/lib/tls/tls_reader.h
index cbe05b41a..d31bf7ef4 100644
--- a/src/lib/tls/tls_reader.h
+++ b/src/lib/tls/tls_reader.h
@@ -203,11 +203,11 @@ void append_tls_length_value(std::vector<uint8_t, Alloc>& buf,
       throw Invalid_Argument("append_tls_length_value: value too large");
 
    for(size_t i = 0; i != tag_size; ++i)
-      buf.push_back(get_byte(sizeof(val_bytes)-tag_size+i, val_bytes));
+      buf.push_back(get_byte_var(sizeof(val_bytes)-tag_size+i, val_bytes));
 
    for(size_t i = 0; i != vals_size; ++i)
       for(size_t j = 0; j != T_size; ++j)
-         buf.push_back(get_byte(j, vals[i]));
+         buf.push_back(get_byte_var(j, vals[i]));
    }
 
 template<typename T, typename Alloc, typename Alloc2>
diff --git a/src/lib/tls/tls_record.cpp b/src/lib/tls/tls_record.cpp
index 6682b871f..5e0a70aa9 100644
--- a/src/lib/tls/tls_record.cpp
+++ b/src/lib/tls/tls_record.cpp
@@ -170,8 +170,8 @@ Connection_Cipher_State::format_ad(uint64_t msg_sequence,
    ad[8] = msg_type;
    ad[9] = version.major_version();
    ad[10] = version.minor_version();
-   ad[11] = get_byte(0, msg_length);
-   ad[12] = get_byte(1, msg_length);
+   ad[11] = get_byte<0>(msg_length);
+   ad[12] = get_byte<1>(msg_length);
 
    return ad;
    }
@@ -182,8 +182,8 @@ inline void append_u16_len(secure_vector<uint8_t>& output, size_t len_field)
    {
    const uint16_t len16 = static_cast<uint16_t>(len_field);
    BOTAN_ASSERT_EQUAL(len_field, len16, "No truncation");
-   output.push_back(get_byte(0, len16));
-   output.push_back(get_byte(1, len16));
+   output.push_back(get_byte<0>(len16));
+   output.push_back(get_byte<1>(len16));
    }
 
 void write_record_header(secure_vector<uint8_t>& output,
@@ -200,7 +200,7 @@ void write_record_header(secure_vector<uint8_t>& output,
    if(version.is_datagram_protocol())
       {
       for(size_t i = 0; i != 8; ++i)
-         output.push_back(get_byte(i, record_sequence));
+         output.push_back(get_byte_var(i, record_sequence));
       }
    }
 
diff --git a/src/lib/utils/cpuid/cpuid_x86.cpp b/src/lib/utils/cpuid/cpuid_x86.cpp
index fb0c2fbcd..88c8a9d8f 100644
--- a/src/lib/utils/cpuid/cpuid_x86.cpp
+++ b/src/lib/utils/cpuid/cpuid_x86.cpp
@@ -124,13 +124,13 @@ uint64_t CPUID::CPUID_Data::detect_cpu_features(size_t* cache_line_size)
    if(is_intel)
       {
       // Intel cache line size is in cpuid(1) output
-      *cache_line_size = 8 * get_byte(2, cpuid[1]);
+      *cache_line_size = 8 * get_byte<2>(cpuid[1]);
       }
    else if(is_amd)
       {
       // AMD puts it in vendor zone
       invoke_cpuid(0x80000005, cpuid);
-      *cache_line_size = get_byte(3, cpuid[2]);
+      *cache_line_size = get_byte<3>(cpuid[2]);
       }
 
    if(max_supported_sublevel >= 7)
diff --git a/src/lib/utils/loadstor.h b/src/lib/utils/loadstor.h
index 3ee4b2461..5824c1218 100644
--- a/src/lib/utils/loadstor.h
+++ b/src/lib/utils/loadstor.h
@@ -36,13 +36,27 @@ namespace Botan {
 * @param input the value to extract from
 * @return byte byte_num of input
 */
-template<typename T> inline constexpr uint8_t get_byte(size_t byte_num, T input)
+template<typename T> inline constexpr uint8_t get_byte_var(size_t byte_num, T input)
    {
    return static_cast<uint8_t>(
       input >> (((~byte_num)&(sizeof(T)-1)) << 3)
       );
    }
 
+/**
+* Byte extraction
+* @param byte_num which byte to extract, 0 == highest byte
+* @param input the value to extract from
+* @return byte byte_num of input
+*/
+template<size_t B, typename T> inline constexpr uint8_t get_byte(T input)
+   {
+   static_assert(B < sizeof(T), "Valid byte offset");
+
+   const size_t shift = ((~B) & (sizeof(T) - 1)) << 3;
+   return static_cast<uint8_t>((input >> shift) & 0xFF);
+   }
+
 /**
 * Make a uint16_t from two bytes
 * @param i0 the first byte
@@ -439,8 +453,8 @@ inline constexpr void store_be(uint16_t in, uint8_t out[2])
    uint16_t o = BOTAN_ENDIAN_N2B(in);
    typecast_copy(out, o);
 #else
-   out[0] = get_byte(0, in);
-   out[1] = get_byte(1, in);
+   out[0] = get_byte<0>(in);
+   out[1] = get_byte<1>(in);
 #endif
    }
 
@@ -455,8 +469,8 @@ inline constexpr void store_le(uint16_t in, uint8_t out[2])
    uint16_t o = BOTAN_ENDIAN_N2L(in);
    typecast_copy(out, o);
 #else
-   out[0] = get_byte(1, in);
-   out[1] = get_byte(0, in);
+   out[0] = get_byte<1>(in);
+   out[1] = get_byte<0>(in);
 #endif
    }
 
@@ -471,10 +485,10 @@ inline constexpr void store_be(uint32_t in, uint8_t out[4])
    uint32_t o = BOTAN_ENDIAN_B2N(in);
    typecast_copy(out, o);
 #else
-   out[0] = get_byte(0, in);
-   out[1] = get_byte(1, in);
-   out[2] = get_byte(2, in);
-   out[3] = get_byte(3, in);
+   out[0] = get_byte<0>(in);
+   out[1] = get_byte<1>(in);
+   out[2] = get_byte<2>(in);
+   out[3] = get_byte<3>(in);
 #endif
    }
 
@@ -489,10 +503,10 @@ inline constexpr void store_le(uint32_t in, uint8_t out[4])
    uint32_t o = BOTAN_ENDIAN_L2N(in);
    typecast_copy(out, o);
 #else
-   out[0] = get_byte(3, in);
-   out[1] = get_byte(2, in);
-   out[2] = get_byte(1, in);
-   out[3] = get_byte(0, in);
+   out[0] = get_byte<3>(in);
+   out[1] = get_byte<2>(in);
+   out[2] = get_byte<1>(in);
+   out[3] = get_byte<0>(in);
 #endif
    }
 
@@ -507,14 +521,14 @@ inline constexpr void store_be(uint64_t in, uint8_t out[8])
    uint64_t o = BOTAN_ENDIAN_B2N(in);
    typecast_copy(out, o);
 #else
-   out[0] = get_byte(0, in);
-   out[1] = get_byte(1, in);
-   out[2] = get_byte(2, in);
-   out[3] = get_byte(3, in);
-   out[4] = get_byte(4, in);
-   out[5] = get_byte(5, in);
-   out[6] = get_byte(6, in);
-   out[7] = get_byte(7, in);
+   out[0] = get_byte<0>(in);
+   out[1] = get_byte<1>(in);
+   out[2] = get_byte<2>(in);
+   out[3] = get_byte<3>(in);
+   out[4] = get_byte<4>(in);
+   out[5] = get_byte<5>(in);
+   out[6] = get_byte<6>(in);
+   out[7] = get_byte<7>(in);
 #endif
    }
 
@@ -529,14 +543,14 @@ inline constexpr void store_le(uint64_t in, uint8_t out[8])
    uint64_t o = BOTAN_ENDIAN_L2N(in);
    typecast_copy(out, o);
 #else
-   out[0] = get_byte(7, in);
-   out[1] = get_byte(6, in);
-   out[2] = get_byte(5, in);
-   out[3] = get_byte(4, in);
-   out[4] = get_byte(3, in);
-   out[5] = get_byte(2, in);
-   out[6] = get_byte(1, in);
-   out[7] = get_byte(0, in);
+   out[0] = get_byte<7>(in);
+   out[1] = get_byte<6>(in);
+   out[2] = get_byte<5>(in);
+   out[3] = get_byte<4>(in);
+   out[4] = get_byte<3>(in);
+   out[5] = get_byte<2>(in);
+   out[6] = get_byte<1>(in);
+   out[7] = get_byte<0>(in);
 #endif
    }
 
@@ -664,7 +678,7 @@ void copy_out_be(uint8_t out[], size_t out_bytes, const T in[])
    }
 
    for(size_t i = 0; i != out_bytes; ++i)
-      out[i] = get_byte(i%8, in[0]);
+      out[i] = get_byte_var(i % 8, in[0]);
    }
 
 template<typename T, typename Alloc>
@@ -685,7 +699,7 @@ void copy_out_le(uint8_t out[], size_t out_bytes, const T in[])
    }
 
    for(size_t i = 0; i != out_bytes; ++i)
-      out[i] = get_byte(sizeof(T) - 1 - (i % 8), in[0]);
+      out[i] = get_byte_var(sizeof(T) - 1 - (i % 8), in[0]);
    }
 
 template<typename T, typename Alloc>
diff --git a/src/lib/utils/parsing.cpp b/src/lib/utils/parsing.cpp
index 09ca432ad..d44e59fc6 100644
--- a/src/lib/utils/parsing.cpp
+++ b/src/lib/utils/parsing.cpp
@@ -180,12 +180,16 @@ uint32_t string_to_ipv4(const std::string& str)
 std::string ipv4_to_string(uint32_t ip)
    {
    std::string str;
+   uint8_t bits[4];
+   store_be(ip, bits);
 
-   for(size_t i = 0; i != sizeof(ip); ++i)
+   for(size_t i = 0; i != 4; ++i)
       {
-      if(i)
+      if(i > 0)
+         {
          str += ".";
-      str += std::to_string(get_byte(i, ip));
+         }
+      str += std::to_string(bits[i]);
       }
 
    return str;


Test patch:
diff --git a/src/tests/test_tls_messages.cpp b/src/tests/test_tls_messages.cpp
index 3e3c41465..37cdb036f 100644
--- a/src/tests/test_tls_messages.cpp
+++ b/src/tests/test_tls_messages.cpp
@@ -79,8 +79,8 @@ class TLS_Message_Parsing_Test final : public Text_Based_Test
                   for(Botan::TLS::Handshake_Extension_Type const& type : message.extension_types())
                      {
                      uint16_t u16type = static_cast<uint16_t>(type);
-                     buf.push_back(Botan::get_byte(0, u16type));
-                     buf.push_back(Botan::get_byte(1, u16type));
+                     buf.push_back(Botan::get_byte<0>(u16type));
+                     buf.push_back(Botan::get_byte<1>(u16type));
                      }
                   result.test_eq("Hello extensions", Botan::hex_encode(buf), extensions);
                   }
@@ -108,8 +108,8 @@ class TLS_Message_Parsing_Test final : public Text_Based_Test
                   for(Botan::TLS::Handshake_Extension_Type const& type : message.extension_types())
                      {
                      uint16_t u16type = static_cast<uint16_t>(type);
-                     buf.push_back(Botan::get_byte(0, u16type));
-                     buf.push_back(Botan::get_byte(1, u16type));
+                     buf.push_back(Botan::get_byte<0>(u16type));
+                     buf.push_back(Botan::get_byte<1>(u16type));
                      }
                   result.test_eq("Hello extensions", Botan::hex_encode(buf), extensions);
                   }
diff --git a/src/tests/test_utils.cpp b/src/tests/test_utils.cpp
index b61253017..470b5eb2f 100644
--- a/src/tests/test_utils.cpp
+++ b/src/tests/test_utils.cpp
@@ -99,10 +99,10 @@ class Utility_Function_Tests final : public Text_Based_Test
          const uint32_t in32 = 0xA0B0C0D0;
          const uint64_t in64 = 0xABCDEF0123456789;
 
-         result.test_is_eq<uint8_t>(Botan::get_byte(0, in32), 0xA0);
-         result.test_is_eq<uint8_t>(Botan::get_byte(1, in32), 0xB0);
-         result.test_is_eq<uint8_t>(Botan::get_byte(2, in32), 0xC0);
-         result.test_is_eq<uint8_t>(Botan::get_byte(3, in32), 0xD0);
+         result.test_is_eq<uint8_t>(Botan::get_byte<0>(in32), 0xA0);
+         result.test_is_eq<uint8_t>(Botan::get_byte<1>(in32), 0xB0);
+         result.test_is_eq<uint8_t>(Botan::get_byte<2>(in32), 0xC0);
+         result.test_is_eq<uint8_t>(Botan::get_byte<3>(in32), 0xD0);
 
          result.test_is_eq<uint16_t>(Botan::make_uint16(0xAA, 0xBB), 0xAABB);
          result.test_is_eq<uint32_t>(Botan::make_uint32(0x01, 0x02, 0x03, 0x04), 0x01020304);