aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2017-08-15 14:34:06 -0400
committerJack Lloyd <[email protected]>2017-08-15 14:34:06 -0400
commit2266362024009f0364a07dd1bcff5115180f40a7 (patch)
tree18804ff157bab625de6c095099f74971e529b566 /src
parentba2c6c7b020497178776b4574ed329586f97c211 (diff)
Improve polynomial doubling code, move to util
Now does 64-bits at a time instead of 8 bits, and avoids conditional timing channel on the XOR carry. Confirmed that at least GCC 7 and Clang 4 on x86-64 compile the functions without conditional jumps. Also removes CMAC as a dependency of OCB, which only needed it in order to call CMAC::poly_double
Diffstat (limited to 'src')
-rw-r--r--src/lib/mac/cmac/cmac.cpp42
-rw-r--r--src/lib/modes/aead/ocb/info.txt4
-rw-r--r--src/lib/modes/aead/ocb/ocb.cpp6
-rw-r--r--src/lib/modes/aead/siv/siv.cpp7
-rw-r--r--src/lib/utils/info.txt1
-rw-r--r--src/lib/utils/poly_dbl.cpp129
-rw-r--r--src/lib/utils/poly_dbl.h25
-rw-r--r--src/tests/data/poly_dbl.vec240
-rw-r--r--src/tests/test_utils.cpp22
9 files changed, 431 insertions, 45 deletions
diff --git a/src/lib/mac/cmac/cmac.cpp b/src/lib/mac/cmac/cmac.cpp
index bb862196f..4d76e4a20 100644
--- a/src/lib/mac/cmac/cmac.cpp
+++ b/src/lib/mac/cmac/cmac.cpp
@@ -6,6 +6,7 @@
*/
#include <botan/cmac.h>
+#include <botan/internal/poly_dbl.h>
namespace Botan {
@@ -14,41 +15,8 @@ namespace Botan {
*/
secure_vector<uint8_t> CMAC::poly_double(const secure_vector<uint8_t>& in)
{
- const bool top_carry = static_cast<bool>((in[0] & 0x80) != 0);
-
secure_vector<uint8_t> out = in;
-
- uint8_t carry = 0;
- for(size_t i = out.size(); i != 0; --i)
- {
- uint8_t temp = out[i-1];
- out[i-1] = (temp << 1) | carry;
- carry = (temp >> 7);
- }
-
- if(top_carry)
- {
- switch(in.size())
- {
- case 8:
- out[out.size()-1] ^= 0x1B;
- break;
- case 16:
- out[out.size()-1] ^= 0x87;
- break;
- case 32:
- out[out.size()-2] ^= 0x4;
- out[out.size()-1] ^= 0x25;
- break;
- case 64:
- out[out.size()-2] ^= 0x1;
- out[out.size()-1] ^= 0x25;
- break;
- default:
- throw Exception("Unsupported CMAC size " + std::to_string(in.size()));
- }
- }
-
+ poly_double_n(out.data(), out.size());
return out;
}
@@ -112,8 +80,10 @@ void CMAC::key_schedule(const uint8_t key[], size_t length)
clear();
m_cipher->set_key(key, length);
m_cipher->encrypt(m_B);
- m_B = poly_double(m_B);
- m_P = poly_double(m_B);
+ poly_double_n(m_B.data(), m_B.size());
+
+ m_P = m_B;
+ poly_double_n(m_P.data(), m_P.size());
}
/*
diff --git a/src/lib/modes/aead/ocb/info.txt b/src/lib/modes/aead/ocb/info.txt
index 738d7c20e..ab4c5297e 100644
--- a/src/lib/modes/aead/ocb/info.txt
+++ b/src/lib/modes/aead/ocb/info.txt
@@ -1,7 +1,3 @@
<defines>
AEAD_OCB -> 20131128
</defines>
-
-<requires>
-cmac
-</requires>
diff --git a/src/lib/modes/aead/ocb/ocb.cpp b/src/lib/modes/aead/ocb/ocb.cpp
index e1fae911b..42118c25c 100644
--- a/src/lib/modes/aead/ocb/ocb.cpp
+++ b/src/lib/modes/aead/ocb/ocb.cpp
@@ -7,7 +7,7 @@
*/
#include <botan/ocb.h>
-#include <botan/cmac.h>
+#include <botan/internal/poly_dbl.h>
#include <botan/internal/bit_ops.h>
namespace Botan {
@@ -56,7 +56,9 @@ class L_computer
secure_vector<uint8_t> poly_double(const secure_vector<uint8_t>& in) const
{
- return CMAC::poly_double(in);
+ secure_vector<uint8_t> out = in;
+ poly_double_n(out.data(), out.size());
+ return out;
}
secure_vector<uint8_t> m_L_dollar, m_L_star;
diff --git a/src/lib/modes/aead/siv/siv.cpp b/src/lib/modes/aead/siv/siv.cpp
index c4db3d785..70545243b 100644
--- a/src/lib/modes/aead/siv/siv.cpp
+++ b/src/lib/modes/aead/siv/siv.cpp
@@ -8,6 +8,7 @@
#include <botan/siv.h>
#include <botan/cmac.h>
+#include <botan/internal/poly_dbl.h>
#include <botan/ctr.h>
#include <botan/parsing.h>
@@ -106,19 +107,19 @@ secure_vector<uint8_t> SIV_Mode::S2V(const uint8_t* text, size_t text_len)
for(size_t i = 0; i != m_ad_macs.size(); ++i)
{
- V = CMAC::poly_double(V);
+ poly_double_n(V.data(), V.size());
V ^= m_ad_macs[i];
}
if(m_nonce.size())
{
- V = CMAC::poly_double(V);
+ poly_double_n(V.data(), V.size());
V ^= m_nonce;
}
if(text_len < 16)
{
- V = CMAC::poly_double(V);
+ poly_double_n(V.data(), V.size());
xor_buf(V.data(), text, text_len);
V[text_len] ^= 0x80;
return m_cmac->process(V);
diff --git a/src/lib/utils/info.txt b/src/lib/utils/info.txt
index 193145c5d..cd0b4bc45 100644
--- a/src/lib/utils/info.txt
+++ b/src/lib/utils/info.txt
@@ -32,6 +32,7 @@ ct_utils.h
donna128.h
filesystem.h
os_utils.h
+poly_dbl.h
prefetch.h
rounding.h
safeint.h
diff --git a/src/lib/utils/poly_dbl.cpp b/src/lib/utils/poly_dbl.cpp
new file mode 100644
index 000000000..0cea4957b
--- /dev/null
+++ b/src/lib/utils/poly_dbl.cpp
@@ -0,0 +1,129 @@
+/*
+* (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 {
+
+void poly_double_n(uint8_t b[], size_t n)
+ {
+ if(n == 8)
+ return poly_double_8(b);
+ else if(n == 16)
+ return poly_double_16(b);
+ else if(n == 24)
+ return poly_double_24(b);
+ else if(n == 32)
+ return poly_double_32(b);
+ else if(n == 64)
+ return poly_double_64(b);
+ else
+ throw Invalid_Argument("Unsupported size for poly_double_n");
+ }
+
+void poly_double_8(uint8_t b[8])
+ {
+ const uint64_t poly = 0x1B;
+ uint64_t b0 = load_be<uint64_t>(b, 0);
+ const uint64_t carry0 = (b0 >> 63);
+ b0 = (b0 << 1) ^ (carry0 * poly);
+ store_be(b0, b);
+ }
+
+void poly_double_16(uint8_t b[16])
+ {
+ const uint64_t poly = 0x87;
+
+ uint64_t b0 = load_be<uint64_t>(b, 0);
+ uint64_t b1 = load_be<uint64_t>(b, 1);
+
+ const uint64_t carry0 = (b0 >> 63);
+
+ b0 = (b0 << 1) ^ (b1 >> 63);
+ b1 = (b1 << 1) ^ (carry0 * poly);
+
+ store_be(b0, b);
+ store_be(b1, b+8);
+ }
+
+void poly_double_24(uint8_t b[24])
+ {
+ const uint64_t poly = 0x87;
+
+ uint64_t b0 = load_be<uint64_t>(b, 0);
+ uint64_t b1 = load_be<uint64_t>(b, 1);
+ uint64_t b2 = load_be<uint64_t>(b, 2);
+
+ const uint64_t carry0 = (b0 >> 63);
+
+ b0 = (b0 << 1) ^ (b1 >> 63);
+ b1 = (b1 << 1) ^ (b2 >> 63);
+ b2 = (b2 << 1) ^ (carry0 * poly);
+
+ store_be(b0, b);
+ store_be(b1, b+8);
+ store_be(b2, b+16);
+ }
+
+void poly_double_32(uint8_t b[32])
+ {
+ const uint64_t poly = 0x425;
+
+ uint64_t b0 = load_be<uint64_t>(b, 0);
+ uint64_t b1 = load_be<uint64_t>(b, 1);
+ uint64_t b2 = load_be<uint64_t>(b, 2);
+ uint64_t b3 = load_be<uint64_t>(b, 3);
+
+ const uint64_t carry0 = (b0 >> 63);
+
+ b0 = (b0 << 1) ^ (b1 >> 63);
+ b1 = (b1 << 1) ^ (b2 >> 63);
+ b2 = (b2 << 1) ^ (b3 >> 63);
+ b3 = (b3 << 1) ^ (carry0 * poly);
+
+ store_be(b0, b);
+ store_be(b1, b+8);
+ store_be(b2, b+16);
+ store_be(b3, b+24);
+ }
+
+void poly_double_64(uint8_t b[64])
+ {
+ const uint64_t poly = 0x125;
+
+ uint64_t b0 = load_be<uint64_t>(b, 0);
+ uint64_t b1 = load_be<uint64_t>(b, 1);
+ uint64_t b2 = load_be<uint64_t>(b, 2);
+ uint64_t b3 = load_be<uint64_t>(b, 3);
+ uint64_t b4 = load_be<uint64_t>(b, 4);
+ uint64_t b5 = load_be<uint64_t>(b, 5);
+ uint64_t b6 = load_be<uint64_t>(b, 6);
+ uint64_t b7 = load_be<uint64_t>(b, 7);
+
+ const uint64_t carry0 = (b0 >> 63);
+
+ b0 = (b0 << 1) ^ (b1 >> 63);
+ b1 = (b1 << 1) ^ (b2 >> 63);
+ b2 = (b2 << 1) ^ (b3 >> 63);
+ b3 = (b3 << 1) ^ (b4 >> 63);
+ b4 = (b4 << 1) ^ (b5 >> 63);
+ b5 = (b5 << 1) ^ (b6 >> 63);
+ b6 = (b6 << 1) ^ (b7 >> 63);
+ b7 = (b7 << 1) ^ (carry0 * poly);
+
+ store_be(b0, b);
+ store_be(b1, b+8);
+ store_be(b2, b+16);
+ store_be(b3, b+24);
+ store_be(b4, b+32);
+ store_be(b5, b+40);
+ store_be(b6, b+48);
+ store_be(b7, b+56);
+ }
+
+}
diff --git a/src/lib/utils/poly_dbl.h b/src/lib/utils/poly_dbl.h
new file mode 100644
index 000000000..df3b419c3
--- /dev/null
+++ b/src/lib/utils/poly_dbl.h
@@ -0,0 +1,25 @@
+/*
+* (C) 2017 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_POLY_DBL_H__
+#define BOTAN_POLY_DBL_H__
+
+#include <botan/types.h>
+
+namespace Botan {
+
+void BOTAN_DLL poly_double_n(uint8_t b[], size_t n);
+
+void poly_double_8(uint8_t b[8]);
+void poly_double_16(uint8_t b[16]);
+void poly_double_24(uint8_t b[24]);
+void poly_double_32(uint8_t b[32]);
+void poly_double_64(uint8_t b[64]);
+
+
+}
+
+#endif
diff --git a/src/tests/data/poly_dbl.vec b/src/tests/data/poly_dbl.vec
new file mode 100644
index 000000000..fb5326f07
--- /dev/null
+++ b/src/tests/data/poly_dbl.vec
@@ -0,0 +1,240 @@
+In = C673FFECCDABFB46
+Out = 8CE7FFD99B57F697
+
+In = C2F801E7762E33C9
+Out = 85F003CEEC5C6789
+
+In = 660D31A3250501E9
+Out = CC1A63464A0A03D2
+
+In = D4B2C6B411807421
+Out = A9658D682300E859
+
+In = DC703E41FC3EFF97
+Out = B8E07C83F87DFF35
+
+In = DC96382AB0FBAF54
+Out = B92C705561F75EB3
+
+In = 185CFF0143FA3A29
+Out = 30B9FE0287F47452
+
+In = E6FF7C75BE895CA8
+Out = CDFEF8EB7D12B94B
+
+In = 0FB1F105F7FFA1E5
+Out = 1F63E20BEFFF43CA
+
+In = 0BD047BD23011C64
+Out = 17A08F7A460238C8
+
+In = 145A5E793B641109
+Out = 28B4BCF276C82212
+
+In = AAAC1B803BCD5047
+Out = 55583700779AA095
+
+In = 01BB22019BF5801A
+Out = 0376440337EB0034
+
+In = 012329A40180CAE8
+Out = 02465348030195D0
+
+In = 32E04D345F77CB05
+Out = 65C09A68BEEF960A
+
+In = 862B1AA2707304D3
+Out = 0C563544E0E609BD
+
+In = 94AFF09E3201FD4E08D48A549AFFD580
+Out = 295FE13C6403FA9C11A914A935FFAB87
+
+In = 01445B8ED79BFFE5FF33CD842DD44732
+Out = 0288B71DAF37FFCBFE679B085BA88E64
+
+In = 014A302085FB07FFEC8020863EFFEC67
+Out = 029460410BF60FFFD900410C7DFFD8CE
+
+In = B750E380D9F7A010F6FF01B444FA6923
+Out = 6EA1C701B3EF4021EDFE036889F4D2C1
+
+In = 1A697E7E25485394319057EEBCE5CFFF
+Out = 34D2FCFC4A90A7286320AFDD79CB9FFE
+
+In = E95E60D2D0FAD8E86664D987655A3F80
+Out = D2BCC1A5A1F5B1D0CCC9B30ECAB47F87
+
+In = 447C8957D3AD868017858C80F1C0BBFC
+Out = 88F912AFA75B0D002F0B1901E38177F8
+
+In = 666180AFBCB42FFF2701ACFFB8112DEF
+Out = CCC3015F79685FFE4E0359FF70225BDE
+
+In = 89B635C72467ED124502E5FF9D09A5C1
+Out = 136C6B8E48CFDA248A05CBFF3A134B05
+
+In = 1FAACA499016BA7AF2A899C22A0861C3
+Out = 3F559493202D74F5E55133845410C386
+
+In = 5E03DAD719D299790056D401FED94591
+Out = BC07B5AE33A532F200ADA803FDB28B22
+
+In = 01C9D901FF2F15FF61139EFC8171A6AB
+Out = 0393B203FE5E2BFEC2273DF902E34D56
+
+In = CF4B3AA7767EFFEBFDC3670D8C4EBD7C
+Out = 9E96754EECFDFFD7FB86CE1B189D7A7F
+
+In = 6A5B3CFFB27201F3FFF0FF8067995B01
+Out = D4B679FF64E403E7FFE1FF00CF32B602
+
+In = 8E98FF03BC0D9BAB8098FFE5D67DC501
+Out = 1D31FE07781B37570131FFCBACFB8A85
+
+In = 212D02B9C91F970C89012101FFFF80FD
+Out = 425A0573923F2E1912024203FFFF01FA
+
+In = 16A1E3D2D24B61556CDDBCED13E5C7ABA4811C1AEB243B1E
+Out = 2D43C7A5A496C2AAD9BB79DA27CB8F5749023835D648763C
+
+In = AC6AF346FF2B0E80EB1F3AC02ABAF8C7017380FF0422FF4D
+Out = 58D5E68DFE561D01D63E75805575F18E02E701FE0845FE1D
+
+In = B5030D0D5D9B78D54C860FF29C0DFAD8B550FD092AE2FB13
+Out = 6A061A1ABB36F1AA990C1FE5381BF5B16AA1FA1255C5F6A1
+
+In = 5431324E7675B621282ECF80DC9C191E4AD1734A7B5A0D9C
+Out = A862649CECEB6C42505D9F01B938323C95A2E694F6B41B38
+
+In = ED5B02B53DB602C424C8B58030DBE0FD01C8FF4DA807E1FF
+Out = DAB6056A7B6C058849916B0061B7C1FA0391FE9B500FC379
+
+In = A6571DF06E0281A0F847E380984118A8C8A2FF01F4FE0148
+Out = 4CAE3BE0DC050341F08FC701308231519145FE03E9FC0217
+
+In = 2D15CB8F6D46863F8D712CA46ABA39FF01EA8C8701F5AB01
+Out = 5A2B971EDA8D0C7F1AE25948D57473FE03D5190E03EB5602
+
+In = 90900102114DE18774767468288F013ACC94E85E8ADEB701
+Out = 21200204229BC30EE8ECE8D0511E02759929D0BD15BD6E85
+
+In = 1869692F085475D1054384C001969E0C65E60222CC28EF34
+Out = 30D2D25E10A8EBA20A870980032D3C18CBCC04459851DE68
+
+In = 66E05387E4018267FF01C4FFE676FF4F0DC6CD30154EF49D
+Out = CDC0A70FC80304CFFE0389FFCCEDFE9E1B8D9A602A9DE93A
+
+In = D15D326201D836C8BF5C83CDFF3C5A80B63D806FF7AB0082
+Out = A2BA64C403B06D917EB9079BFE78B5016C7B00DFEF560183
+
+In = 787EDEFFABBE80EF382201356AA355F2F5AF3A14432AFF55
+Out = F0FDBDFF577D01DE7044026AD546ABE5EB5E74288655FEAA
+
+In = 3CAFA39315F2FF65C9B590FD2B6442AB71E2DC62A31D31A4
+Out = 795F47262BE5FECB936B21FA56C88556E3C5B8C5463A6348
+
+In = DC734911B0CAAB250108894D38D11E8701E19CFC9F239FDE
+Out = B8E692236195564A0211129A71A23D0E03C339F93E473F3B
+
+In = EACC15239A807DEFFF1ED311687C1A01F944AC010E644DFF
+Out = D5982A473500FBDFFE3DA622D0F83403F28958021CC89B79
+
+In = 7B2B0D80C866D4BBFD01DC6C74FFB13F6B799068D3C4601B
+Out = F6561B0190CDA977FA03B8D8E9FF627ED6F320D1A788C036
+
+In = 01186E8B7DE2804DAEB71364E9AB70808BCD58971680F8927AFF6780CB62FF10
+Out = 0230DD16FBC5009B5D6E26C9D356E101179AB12E2D01F124F5FECF0196C5FE20
+
+In = 45FD23C43875897401EFB2C29A53900DFF63FF8601D959319A7AA7AAF2F841D1
+Out = 8BFA478870EB12E803DF658534A7201BFEC7FF0C03B2B26334F54F55E5F083A2
+
+In = 8BB1E02D1CFF75BCC5FF4EE41A3D80019ACD8FB2B652E5478084A1241F01F57D
+Out = 1763C05A39FEEB798BFE9DC8347B0003359B1F656CA5CA8F010942483E03EEDF
+
+In = 8017A58CEFDA4EB3F3C39AB2B5DBC69D0ED3F2D75BB05DD327C8FA804CCF806C
+Out = 002F4B19DFB49D67E78735656BB78D3A1DA7E5AEB760BBA64F91F500999F04FD
+
+In = 9FBC1301F4DB1F088A89F1CD3301035D16904FEE9854844417016537B8A27EFF
+Out = 3F782603E9B63E111513E39A660206BA2D209FDD30A908882E02CA6F7144F9DB
+
+In = 95BB4B56F7194078BEB8515FF6C92FDCC62C8083EEEF7E9953EED6DB22C7BBB0
+Out = 2B7696ADEE3280F17D70A2BFED925FB98C590107DDDEFD32A7DDADB6458F7345
+
+In = 56AC3F3E6E4EC2220111446C5F08B4E2EFE0698096C26ACD9B9E7E993AC8454F
+Out = AD587E7CDC9D8444022288D8BE1169C5DFC0D3012D84D59B373CFD3275908A9E
+
+In = 515AE33EE8FF522B207DE4E6926DBD4E1F90AA06E2FF35AE8014F9EA9D57FF14
+Out = A2B5C67DD1FEA45640FBC9CD24DB7A9C3F21540DC5FE6B5D0029F3D53AAFFE28
+
+In = CAF8DB3CC6B8E25801FF939DDEFB44490193806E0E9AFC51BFEA86C3FC5DD66E
+Out = 95F1B6798D71C4B003FF273BBDF68892032700DC1D35F8A37FD50D87F8BBA8F9
+
+In = BDB281A665FEA84A312CB2DA90A5D8809537440EBDD201225E9D0A79FEFF016F
+Out = 7B65034CCBFD5094625965B5214BB1012A6E881D7BA40244BD3A14F3FDFE06FB
+
+In = B7882CBDFE426444C9D92DB5C7B057D58080874DC4D6FF3ADC3099AC4B430256
+Out = 6F10597BFC84C88993B25B6B8F60AFAB01010E9B89ADFE75B861335896860089
+
+In = FA36EBA53A0789A802E56E18E3B88180FF72D3B48E6A2FD759AF74018CB38F69
+Out = F46DD74A740F135005CADC31C7710301FEE5A7691CD45FAEB35EE80319671AF7
+
+In = A110B893FD9BB169E838B7F62C2B425A79C2D962D6688B10149A9D0F3986CF5E
+Out = 42217127FB3762D3D0716FEC585684B4F385B2C5ACD1162029353A1E730D9A99
+
+In = 4A7975F9D8D334D72B1401925D012C1343EDA860A0C6FFA93E4C9D758748FF4F
+Out = 94F2EBF3B1A669AE56280324BA02582687DB50C1418DFF527C993AEB0E91FE9E
+
+In = 83612A4A010CCEFFA9629342FFC976FFB74FD624FF6E017AFF7C1DF180F0581E
+Out = 06C2549402199DFF52C52685FF92EDFF6E9FAC49FEDC02F5FEF83BE301E0B419
+
+In = 950F78870E4F1A8E6FFF801EF01E8600AAC8E21790140F4DC39EBBA2EE8D3618
+Out = 2A1EF10E1C9E351CDFFF003DE03D0C015591C42F20281E9B873D7745DD1A6815
+
+In = 229AFFB2B282E7DE732256E9FFA9411CC13B430D0F33CC7F57019E527331FF11BB5E2E53522103693E9C5E80FF7F1885A1FC37A065ED787472A1800001E68A1C
+Out = 4535FF656505CFBCE644ADD3FF5282398276861A1E6798FEAE033CA4E663FE2376BC5CA6A44206D27D38BD01FEFE310B43F86F40CBDAF0E8E543000003CD1438
+
+In = 80BD24865C804F3AEEA9606E4B292230C2FB80B7CA807DA72B65F52088EC9C80CC2848A0FF6A80E823A305AE988003050C6C92A2319FB6012D23F748F2B8E34A
+Out = 017A490CB9009E75DD52C0DC9652446185F7016F9500FB4E56CBEA4111D9390198509141FED501D047460B5D3100060A18D92544633F6C025A47EE91E571C7B1
+
+In = C2EF017F14604C01CF0C14FF01AA80622001A352F612AD140E2E6ED03FDEF8014A63DF39348480FD550F950301EE72113120015E9F257A69869FF1E04CE3DC53
+Out = 85DE02FE28C098039E1829FE035500C4400346A5EC255A281C5CDDA07FBDF00294C7BE72690901FAAA1F2A0603DCE422624002BD3E4AF4D30D3FE3C099C7B983
+
+In = FBBA80186D8A25F9B63BA92DBC82735180F25AE02D4AB0B7318818AAB439B503CC8AB6E6F6A1ABF2C75A72FF26D0FBDC2148882EA90E0A412E41804555758609
+Out = F7750030DB144BF36C77525B7904E6A301E4B5C05A95616E6310315568736A0799156DCDED4357E58EB4E5FE4DA1F7B84291105D521C14825C83008AAAEB0D37
+
+In = EB8C6460E8DECA7873F26326C3E5658DCA012EE340DD6CF001248001473FFF253C808CFA8080F280940BFF801E1FB875E6CC8008B3FEA480FF172AFF2B804ABA
+Out = D718C8C1D1BD94F0E7E4C64D87CACB1B94025DC681BAD9E0024900028E7FFE4A790119F50101E5012817FF003C3F70EBCD99001167FD4901FE2E55FE57009451
+
+In = 66ED47263E72C4A07BFE3593546F4D168AFF806F25639F088FE01601A90A5A96BE0E573005EF7D01BC2834B3E7F4F8C65A801B6BF3280EF962DBD401BEFFB248
+Out = CDDA8E4C7CE58940F7FC6B26A8DE9A2D15FF00DE4AC73E111FC02C035214B52D7C1CAE600BDEFA0378506967CFE9F18CB50036D7E6501DF2C5B7A8037DFF6490
+
+In = F7A8FFC3BB802C43DCEDDD3DE36F3F166F801780DA58E31EBF643875F2643D822B600814F7CAF002E35C01D199F5677CC41A754F8721ACFF5BCA08890A8EFF01
+Out = EF51FF8777005887B9DBBA7BC6DE7E2CDF002F01B4B1C63D7EC870EBE4C87B0456C01029EF95E005C6B803A333EACEF98834EA9F0E4359FEB7941112151DFF27
+
+In = 80EBEE627605DADECBD0F1067180FF80271B8009E3B08C76C0BE29EAFF646972D811ABFD7595808087FFE130FF0101807FD9805789DDFB1A5E8226FF5D37F5A8
+Out = 01D7DCC4EC0BB5BD97A1E20CE301FF004E370013C76118ED817C53D5FEC8D2E5B02357FAEB2B01010FFFC261FE020300FFB300AF13BBF634BD044DFEBA6FEA75
+
+In = FF28977022562ED9C2F7A7011B3808A02ED8F480013401338A804C85ECDEFF010125FA71AE01C02F5327F22679CF4F6EC392FF681B0167D2CAFEBD26309006AD
+Out = FE512EE044AC5DB385EF4E02367011405DB1E900026802671500990BD9BDFE02024BF4E35C03805EA64FE44CF39E9EDD8725FED03602CFA595FD7A4C61200C7F
+
+In = 4B3C77451A8432187B0139FF0101B5378C2F55B56BBA5608958680753F674080FB937797B4FF6F7D90FFB154012805CC01C7E231897F8414FFA5FF56349666D8
+Out = 9678EE8A35086430F60273FE02036A6F185EAB6AD774AC112B0D00EA7ECE8101F726EF2F69FEDEFB21FF62A802500B98038FC46312FF0829FF4BFEAC692CCDB0
+
+In = FFF1B636DCFF39BE6EC0FFC8CD1D80F01678FFCD64FF40FF7A53F2F89DE61EFF12E9BB2D2FD94C01E1BBCC5BAA846394B4C4430A55913FBE3F5580B0D2540CF7
+Out = FFE36C6DB9FE737CDD81FF919A3B01E02CF1FF9AC9FE81FEF4A7E5F13BCC3DFE25D3765A5FB29803C37798B75508C72969888614AB227F7C7EAB0161A4A818CB
+
+In = ABABC192260BC46CF63AFF80D194431B87B94E03F466D7B51029AD3517A36A958524C9B4510128715601A0CB489F3DFFD32E1FFF46A7D1BF012AF20E890483A9
+Out = 575783244C1788D9EC75FF01A32886370F729C07E8CDAF6A20535A6A2F46D52B0A499368A20250E2AC034196913E7BFFA65C3FFE8D4FA37E0255E41D12090677
+
+In = 98889EC9ED30514468D62D16C8014BFFD84969076FB17AFFBE9B415B0C80273801804A3B79A11FE8738C80CDFFF280DF7601773B9AF3809403694880577F136E
+Out = 31113D93DA60A288D1AC5A2D900297FFB092D20EDF62F5FF7D3682B619004E7003009476F3423FD0E719019BFFE501BEEC02EE7735E7012806D29100AEFE27F9
+
+In = 51CA0F9203C2408BAA2BA980FFFF32CBC25081BD958E2917DE16212E707E9E28BB8B0908322ACA46BA56ADFC017B50E77F3C69C3FF591274CDB509A8FF5A4045
+Out = A3941F240784811754575301FFFE659784A1037B2B1C522FBC2C425CE0FD3C51771612106455948D74AD5BF802F6A1CEFE78D387FEB224E99B6A1351FEB4808A
+
+In = 5B87801DF79DE69D8EF5D459D85A019FB9C7E46EAEC42975135D151E8E4A30E64D3B6459801D1560B6DBB79A1EF09CAB27C0BDB256BB720129C3743E01AA8046
+Out = B70F003BEF3BCD3B1DEBA8B3B0B4033F738FC8DD5D8852EA26BA2A3D1C9461CC9A76C8B3003A2AC16DB76F343DE139564F817B64AD76E4025386E87C0355008C
+
+In = E30D8CF9184C855AA05F27B7EE1061DF238052A64452AA6B2FAD9DBC8F86243552F62F0F8F3D0D837292804F2401158787FF7D1AA2EDE287369509184FC674AE
+Out = C61B19F230990AB540BE4F6FDC20C3BE4700A54C88A554D65F5B3B791F0C486AA5EC5E1F1E7A1B06E525009E48022B0F0FFEFA3545DBC50E6D2A12309F8CE879
+
diff --git a/src/tests/test_utils.cpp b/src/tests/test_utils.cpp
index a1e583cd8..0ca79b6e9 100644
--- a/src/tests/test_utils.cpp
+++ b/src/tests/test_utils.cpp
@@ -12,6 +12,7 @@
#include <botan/loadstor.h>
#include <botan/calendar.h>
#include <botan/internal/rounding.h>
+#include <botan/internal/poly_dbl.h>
#include <botan/charset.h>
#include <botan/parsing.h>
@@ -177,6 +178,27 @@ class Utility_Function_Tests : public Text_Based_Test
BOTAN_REGISTER_TEST("util", Utility_Function_Tests);
+class Poly_Double_Tests : public Text_Based_Test
+ {
+ public:
+ Poly_Double_Tests() : Text_Based_Test("poly_dbl.vec", "In,Out") {}
+
+ Test::Result run_one_test(const std::string&, const VarMap& vars) override
+ {
+ Test::Result result("Polynomial doubling");
+ const std::vector<uint8_t> in = get_req_bin(vars, "In");
+ const std::vector<uint8_t> out = get_req_bin(vars, "Out");
+
+ std::vector<uint8_t> b = in;
+ Botan::poly_double_n(b.data(), b.size());
+
+ result.test_eq("Expected value", b, out);
+ return result;
+ }
+ };
+
+BOTAN_REGISTER_TEST("poly_dbl", Poly_Double_Tests);
+
class Date_Format_Tests : public Text_Based_Test
{
public: