diff options
Diffstat (limited to 'src/lib/utils/poly_dbl/poly_dbl.cpp')
-rw-r--r-- | src/lib/utils/poly_dbl/poly_dbl.cpp | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/src/lib/utils/poly_dbl/poly_dbl.cpp b/src/lib/utils/poly_dbl/poly_dbl.cpp new file mode 100644 index 000000000..2b989db57 --- /dev/null +++ b/src/lib/utils/poly_dbl/poly_dbl.cpp @@ -0,0 +1,83 @@ +/* +* (C) 2017 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/internal/poly_dbl.h> +#include <botan/loadstor.h> +#include <botan/exceptn.h> + +namespace Botan { + +namespace { + +template<size_t LIMBS, uint64_t POLY> +void poly_double(uint8_t out[], const uint8_t in[]) + { + uint64_t W[LIMBS]; + load_be(W, in, LIMBS); + + const uint64_t carry = POLY * (W[0] >> 63); + for(size_t i = 0; i != LIMBS - 1; ++i) + W[i] = (W[i] << 1) ^ (W[i+1] >> 63); + W[LIMBS-1] = (W[LIMBS-1] << 1) ^ carry; + + copy_out_be(out, LIMBS*8, W); + } + +template<size_t LIMBS, uint64_t POLY> +void poly_double_le(uint8_t out[], const uint8_t in[]) + { + uint64_t W[LIMBS]; + load_le(W, in, LIMBS); + + const uint64_t carry = POLY * (W[LIMBS-1] >> 63); + for(size_t i = 0; i != LIMBS - 1; ++i) + W[LIMBS-1-i] = (W[LIMBS-1-i] << 1) ^ (W[LIMBS-2-i] >> 63); + W[0] = (W[0] << 1) ^ carry; + + copy_out_le(out, LIMBS*8, W); + } + +} + +void poly_double_n(uint8_t out[], const uint8_t in[], size_t n) + { + switch(n) + { + case 8: + return poly_double<1, 0x1B>(out, in); + case 16: + return poly_double<2, 0x87>(out, in); + case 24: + return poly_double<3, 0x87>(out, in); + case 32: + return poly_double<4, 0x425>(out, in); + case 64: + return poly_double<8, 0x125>(out, in); + default: + throw Invalid_Argument("Unsupported size for poly_double_n"); + } + } + +void poly_double_n_le(uint8_t out[], const uint8_t in[], size_t n) + { + switch(n) + { + case 8: + return poly_double_le<1, 0x1B>(out, in); + case 16: + return poly_double_le<2, 0x87>(out, in); + case 24: + return poly_double_le<3, 0x87>(out, in); + case 32: + return poly_double_le<4, 0x425>(out, in); + case 64: + return poly_double_le<8, 0x125>(out, in); + default: + throw Invalid_Argument("Unsupported size for poly_double_n_le"); + } + } + +} |