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

randombit / botan / 5133556677

31 May 2023 02:11PM UTC coverage: 91.735% (-0.3%) from 92.012%
5133556677

Pull #3568

github

web-flow
Merge de48a2eb6 into 1cbeffafb
Pull Request #3568: Change clang-format AllowShortBlocksOnASingleLine from true to Empty

76059 of 82912 relevant lines covered (91.73%)

12004312.75 hits per line

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

88.24
/src/tests/test_roughtime.cpp
1
/*
2
* (C) 2019 Nuno Goncalves <nunojpg@gmail.com>
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6

7
#include "test_rng.h"
8
#include "tests.h"
9

10
#if defined(BOTAN_HAS_BIGINT)
11
   #include <botan/bigint.h>
12
#endif
13

14
#if defined(BOTAN_HAS_ROUGHTIME)
15
   #include <botan/base64.h>
16
   #include <botan/ed25519.h>
17
   #include <botan/hex.h>
18
   #include <botan/roughtime.h>
19
#endif
20

21
namespace Botan_Tests {
22

23
#if defined(BOTAN_HAS_ROUGHTIME)
24

25
class Roughtime_Request_Tests final : public Text_Based_Test {
×
26
   public:
27
      Roughtime_Request_Tests() : Text_Based_Test("roughtime/roughtime_request.vec", "Nonce,Request") {}
2✔
28

29
      Test::Result run_one_test(const std::string& type, const VarMap& vars) override {
2✔
30
         Test::Result result("Roughtime request");
2✔
31

32
         const auto nonce = vars.get_req_bin("Nonce");
2✔
33
         const auto request_v = vars.get_req_bin("Request");
2✔
34

35
         const auto request = Botan::Roughtime::encode_request(nonce);
2✔
36
         result.test_eq(
2✔
37
            "encode", type == "Valid", request == Botan::typecast_copy<std::array<uint8_t, 1024>>(request_v.data()));
2✔
38

39
         return result;
2✔
40
      }
4✔
41
};
42

43
BOTAN_REGISTER_TEST("roughtime", "roughtime_request", Roughtime_Request_Tests);
44

45
class Roughtime_Response_Tests final : public Text_Based_Test {
×
46
   public:
47
      Roughtime_Response_Tests() :
1✔
48
            Text_Based_Test(
49
               "roughtime/roughtime_response.vec", "Response", "Nonce,Pubkey,MidpointMicroSeconds,RadiusMicroSeconds") {
2✔
50
      }
1✔
51

52
      Test::Result run_one_test(const std::string& type, const VarMap& vars) override {
17✔
53
         Test::Result result("Roughtime response");
17✔
54

55
         const auto response_v = vars.get_req_bin("Response");
17✔
56
         const auto nonce_bits = vars.has_key("Nonce") ? vars.get_opt_bin("Nonce") : std::vector<uint8_t>(64);
40✔
57

58
         const Botan::Roughtime::Nonce nonce(nonce_bits);
17✔
59
         try {
17✔
60
            const auto response = Botan::Roughtime::Response::from_bits(response_v, nonce);
17✔
61

62
            const auto pubkey = vars.get_req_bin("Pubkey");
4✔
63
            if(pubkey.size() != 32) {
4✔
64
               throw Test_Error("Unexpected Roughtime Ed25519 pubkey size");
×
65
            }
66

67
            if(!response.validate(Botan::Ed25519_PublicKey(pubkey))) {
4✔
68
               result.confirm("fail_validation", type == "Invalid");
2✔
69
            } else {
70
               const auto midpoint = Botan::Roughtime::Response::sys_microseconds64(
3✔
71
                  std::chrono::microseconds(vars.get_req_u64("MidpointMicroSeconds")));
3✔
72
               const auto radius = std::chrono::microseconds(vars.get_req_u32("RadiusMicroSeconds"));
3✔
73

74
               result.confirm("midpoint", response.utc_midpoint() == midpoint);
6✔
75
               result.confirm("radius", response.utc_radius() == radius);
6✔
76
               result.confirm("OK", type == "Valid");
6✔
77
            }
78
         } catch(const Botan::Roughtime::Roughtime_Error& e) {
17✔
79
            result.confirm(e.what(), type == "Invalid");
26✔
80
         }
13✔
81

82
         return result;
17✔
83
      }
34✔
84
};
85

86
BOTAN_REGISTER_TEST("roughtime", "roughtime_response", Roughtime_Response_Tests);
87

88
class Roughtime_nonce_from_blind_Tests final : public Text_Based_Test {
×
89
   public:
90
      Roughtime_nonce_from_blind_Tests() :
1✔
91
            Text_Based_Test("roughtime/roughtime_nonce_from_blind.vec", "Response,Blind,Nonce") {}
3✔
92

93
      Test::Result run_one_test(const std::string& type, const VarMap& vars) override {
2✔
94
         Test::Result result("roughtime nonce_from_blind");
2✔
95

96
         const auto response = vars.get_req_bin("Response");
2✔
97
         const auto blind = vars.get_req_bin("Blind");
2✔
98
         const auto nonce = vars.get_req_bin("Nonce");
2✔
99

100
         result.test_eq(
4✔
101
            "fail_validation", Botan::Roughtime::nonce_from_blind(response, blind) == nonce, type == "Valid");
2✔
102

103
         return result;
2✔
104
      }
6✔
105
};
106

107
BOTAN_REGISTER_TEST("roughtime", "roughtime_nonce_from_blind", Roughtime_nonce_from_blind_Tests);
108

109
class Roughtime final : public Test {
×
110
      static Test::Result test_nonce() {
1✔
111
         Test::Result result("roughtime nonce");
1✔
112

113
         auto rand64 = Botan::unlock(Test::rng().random_vec(64));
2✔
114
         Botan::Roughtime::Nonce nonce_v(rand64);
1✔
115
         result.confirm("nonce from vector",
2✔
116
                        nonce_v.get_nonce() == Botan::typecast_copy<std::array<uint8_t, 64>>(rand64.data()));
1✔
117
         Botan::Roughtime::Nonce nonce_a(Botan::typecast_copy<std::array<uint8_t, 64>>(rand64.data()));
1✔
118
         result.confirm("nonce from array",
1✔
119
                        nonce_v.get_nonce() == Botan::typecast_copy<std::array<uint8_t, 64>>(rand64.data()));
1✔
120
         rand64.push_back(10);
1✔
121
         result.test_throws("vector oversize", [&rand64]() { Botan::Roughtime::Nonce nonce_v2(rand64); });  //size 65
3✔
122
         rand64.pop_back();
1✔
123
         rand64.pop_back();
1✔
124
         result.test_throws("vector undersize", [&rand64]() { Botan::Roughtime::Nonce nonce_v2(rand64); });  //size 63
3✔
125

126
         return result;
1✔
127
      }
1✔
128

129
      static Test::Result test_chain() {
1✔
130
         Test::Result result("roughtime chain");
1✔
131

132
         Botan::Roughtime::Chain c1;
1✔
133
         result.confirm("default constructed is empty", c1.links().empty() && c1.responses().empty());
3✔
134

135
         auto rand64 = Botan::unlock(Test::rng().random_vec(64));
2✔
136
         Botan::Roughtime::Nonce nonce_v(rand64);
1✔
137
         result.confirm(
2✔
138
            "empty chain nonce is blind",
139
            c1.next_nonce(nonce_v).get_nonce() == Botan::typecast_copy<std::array<uint8_t, 64>>(rand64.data()));
1✔
140

141
         const std::string chain_str =
1✔
142
            "ed25519 bbT+RPS7zKX6w71ssPibzmwWqU9ffRV5oj2OresSmhE= eu9yhsJfVfguVSqGZdE8WKIxaBBM0ZG3Vmuc+IyZmG2YVmrIktUByDdwIFw6F4rZqmSFsBO85ljoVPz5bVPCOw== BQAAAEAAAABAAAAApAAAADwBAABTSUcAUEFUSFNSRVBDRVJUSU5EWBnGOEajOwPA6G7oL47seBP4C7eEpr57H43C2/fK/kMA0UGZVUdf4KNX8oxOK6JIcsbVk8qhghTwA70qtwpYmQkDAAAABAAAAAwAAABSQURJTUlEUFJPT1RAQg8AJrA8tEqPBQAqisiuAxgy2Pj7UJAiWbCdzGz1xcCnja3T+AqhC8fwpeIwW4GPy/vEb/awXW2DgSLKJfzWIAz+2lsR7t4UjNPvAgAAAEAAAABTSUcAREVMRes9Ch4X0HIw5KdOTB8xK4VDFSJBD/G9t7Et/CU7UW61OiTBXYYQTG2JekWZmGa0OHX1JPGG+APkpbsNw0BKUgYDAAAAIAAAACgAAABQVUJLTUlOVE1BWFR/9BWjpsWTQ1f6iUJea3EfZ1MkX3ftJiV3ABqNLpncFwAAAAAAAAAA//////////8AAAAA\n"
143
            "ed25519 gD63hSj3ScS+wuOeGrubXlq35N1c5Lby/S+T7MNTjxo= uLeTON9D+2HqJMzK6sYWLNDEdtBl9t/9yw1cVAOm0/sONH5Oqdq9dVPkC9syjuWbglCiCPVF+FbOtcxCkrgMmA== BQAAAEAAAABAAAAApAAAADwBAABTSUcAUEFUSFNSRVBDRVJUSU5EWOw1jl0uSiBEH9HE8/6r7zxoSc01f48vw+UzH8+VJoPelnvVJBj4lnH8uRLh5Aw0i4Du7XM1dp2u0r/I5PzhMQoDAAAABAAAAAwAAABSQURJTUlEUFJPT1RAQg8AUBo+tEqPBQC47l77to7ESFTVhlw1SC74P5ssx6gpuJ6eP+1916GuUiySGE/x3Fp0c3otUGAdsRQou5p9PDTeane/YEeVq4/8AgAAAEAAAABTSUcAREVMRe5T1ml8wHyWAcEtHP/U5Rg/jFXTEXOSglngSa4aI/CECVdy4ZNWeP6vv+2//ZW7lQsrWo7ZkXpvm9BdBONRSQIDAAAAIAAAACgAAABQVUJLTUlOVE1BWFQpXlenV0OfVisvp9jDHXLw8vymZVK9Pgw9k6Edf8ZEhUgSGEc5jwUASHLvZE2PBQAAAAAA\n";
1✔
144

145
         Botan::Roughtime::Chain c2(chain_str);
1✔
146
         result.confirm("have two elements", c2.links().size() == 2 && c2.responses().size() == 2);
3✔
147
         result.confirm("serialize loopback", c2.to_string() == chain_str);
3✔
148

149
         c1.append(c2.links()[0], 1);
1✔
150
         result.confirm("append ok", c1.links().size() == 1 && c1.responses().size() == 1);
2✔
151
         c1.append(c2.links()[1], 1);
1✔
152
         result.confirm("max size", c1.links().size() == 1 && c1.responses().size() == 1);
2✔
153

154
         result.test_throws("non-positive max chain size", [&]() { c1.append(c2.links()[1], 0); });
3✔
155
         result.test_throws("1 field", [&]() { Botan::Roughtime::Chain a("ed25519"); });
3✔
156
         result.test_throws(
2✔
157
            "2 fields", [&]() { Botan::Roughtime::Chain a("ed25519 bbT+RPS7zKX6w71ssPibzmwWqU9ffRV5oj2OresSmhE="); });
1✔
158
         result.test_throws("3 fields", [&]() {
2✔
159
            Botan::Roughtime::Chain a(
1✔
160
               "ed25519 bbT+RPS7zKX6w71ssPibzmwWqU9ffRV5oj2OresSmhE= eu9yhsJfVfguVSqGZdE8WKIxaBBM0ZG3Vmuc+IyZmG2YVmrIktUByDdwIFw6F4rZqmSFsBO85ljoVPz5bVPCOw==");
1✔
161
         });
×
162
         result.test_throws("5 fields", [&]() {
2✔
163
            Botan::Roughtime::Chain a(
1✔
164
               "ed25519 bbT+RPS7zKX6w71ssPibzmwWqU9ffRV5oj2OresSmhE= eu9yhsJfVfguVSqGZdE8WKIxaBBM0ZG3Vmuc+IyZmG2YVmrIktUByDdwIFw6F4rZqmSFsBO85ljoVPz5bVPCOw== BQAAAEAAAABAAAAApAAAADwBAABTSUcAUEFUSFNSRVBDRVJUSU5EWBnGOEajOwPA6G7oL47seBP4C7eEpr57H43C2/fK/kMA0UGZVUdf4KNX8oxOK6JIcsbVk8qhghTwA70qtwpYmQkDAAAABAAAAAwAAABSQURJTUlEUFJPT1RAQg8AJrA8tEqPBQAqisiuAxgy2Pj7UJAiWbCdzGz1xcCnja3T+AqhC8fwpeIwW4GPy/vEb/awXW2DgSLKJfzWIAz+2lsR7t4UjNPvAgAAAEAAAABTSUcAREVMRes9Ch4X0HIw5KdOTB8xK4VDFSJBD/G9t7Et/CU7UW61OiTBXYYQTG2JekWZmGa0OHX1JPGG+APkpbsNw0BKUgYDAAAAIAAAACgAAABQVUJLTUlOVE1BWFR/9BWjpsWTQ1f6iUJea3EfZ1MkX3ftJiV3ABqNLpncFwAAAAAAAAAA//////////8AAAAA abc");
1✔
165
         });
×
166
         result.test_throws("invalid key type", [&]() {
2✔
167
            Botan::Roughtime::Chain a(
1✔
168
               "rsa bbT+RPS7zKX6w71ssPibzmwWqU9ffRV5oj2OresSmhE= eu9yhsJfVfguVSqGZdE8WKIxaBBM0ZG3Vmuc+IyZmG2YVmrIktUByDdwIFw6F4rZqmSFsBO85ljoVPz5bVPCOw== BQAAAEAAAABAAAAApAAAADwBAABTSUcAUEFUSFNSRVBDRVJUSU5EWBnGOEajOwPA6G7oL47seBP4C7eEpr57H43C2/fK/kMA0UGZVUdf4KNX8oxOK6JIcsbVk8qhghTwA70qtwpYmQkDAAAABAAAAAwAAABSQURJTUlEUFJPT1RAQg8AJrA8tEqPBQAqisiuAxgy2Pj7UJAiWbCdzGz1xcCnja3T+AqhC8fwpeIwW4GPy/vEb/awXW2DgSLKJfzWIAz+2lsR7t4UjNPvAgAAAEAAAABTSUcAREVMRes9Ch4X0HIw5KdOTB8xK4VDFSJBD/G9t7Et/CU7UW61OiTBXYYQTG2JekWZmGa0OHX1JPGG+APkpbsNw0BKUgYDAAAAIAAAACgAAABQVUJLTUlOVE1BWFR/9BWjpsWTQ1f6iUJea3EfZ1MkX3ftJiV3ABqNLpncFwAAAAAAAAAA//////////8AAAAA");
1✔
169
         });
×
170
         result.test_throws("invalid key", [&]() {
2✔
171
            Botan::Roughtime::Chain a(
1✔
172
               "ed25519 bbT+RPS7zKX6wssPibzmwWqU9ffRV5oj2OresSmhE= eu9yhsJfVfguVSqGZdE8WKIxaBBM0ZG3Vmuc+IyZmG2YVmrIktUByDdwIFw6F4rZqmSFsBO85ljoVPz5bVPCOw== BQAAAEAAAABAAAAApAAAADwBAABTSUcAUEFUSFNSRVBDRVJUSU5EWBnGOEajOwPA6G7oL47seBP4C7eEpr57H43C2/fK/kMA0UGZVUdf4KNX8oxOK6JIcsbVk8qhghTwA70qtwpYmQkDAAAABAAAAAwAAABSQURJTUlEUFJPT1RAQg8AJrA8tEqPBQAqisiuAxgy2Pj7UJAiWbCdzGz1xcCnja3T+AqhC8fwpeIwW4GPy/vEb/awXW2DgSLKJfzWIAz+2lsR7t4UjNPvAgAAAEAAAABTSUcAREVMRes9Ch4X0HIw5KdOTB8xK4VDFSJBD/G9t7Et/CU7UW61OiTBXYYQTG2JekWZmGa0OHX1JPGG+APkpbsNw0BKUgYDAAAAIAAAACgAAABQVUJLTUlOVE1BWFR/9BWjpsWTQ1f6iUJea3EfZ1MkX3ftJiV3ABqNLpncFwAAAAAAAAAA//////////8AAAAA");
1✔
173
         });
×
174
         result.test_throws("invalid nonce", [&]() {
1✔
175
            Botan::Roughtime::Chain a(
1✔
176
               "ed25519 bbT+RPS7zKX6w71ssPibzmwWqU9ffRV5oj2OresSmhE= eu9yhsJfVfguVSqGZdE8WKIxaBBM0ZG3Vmuc+IyZmG2UByDdwIFw6F4rZqmSFsBO85ljoVPz5bVPCOw== BQAAAEAAAABAAAAApAAAADwBAABTSUcAUEFUSFNSRVBDRVJUSU5EWBnGOEajOwPA6G7oL47seBP4C7eEpr57H43C2/fK/kMA0UGZVUdf4KNX8oxOK6JIcsbVk8qhghTwA70qtwpYmQkDAAAABAAAAAwAAABSQURJTUlEUFJPT1RAQg8AJrA8tEqPBQAqisiuAxgy2Pj7UJAiWbCdzGz1xcCnja3T+AqhC8fwpeIwW4GPy/vEb/awXW2DgSLKJfzWIAz+2lsR7t4UjNPvAgAAAEAAAABTSUcAREVMRes9Ch4X0HIw5KdOTB8xK4VDFSJBD/G9t7Et/CU7UW61OiTBXYYQTG2JekWZmGa0OHX1JPGG+APkpbsNw0BKUgYDAAAAIAAAACgAAABQVUJLTUlOVE1BWFR/9BWjpsWTQ1f6iUJea3EfZ1MkX3ftJiV3ABqNLpncFwAAAAAAAAAA//////////8AAAAA");
1✔
177
         });
×
178

179
         return result;
1✔
180
      }
3✔
181

182
      static Test::Result test_server_information() {
1✔
183
         Test::Result result("roughtime server_information");
1✔
184

185
         const auto servers = Botan::Roughtime::servers_from_str(
1✔
186
            "Chainpoint-Roughtime ed25519 bbT+RPS7zKX6w71ssPibzmwWqU9ffRV5oj2OresSmhE= udp roughtime.chainpoint.org:2002\n"
187
            "Cloudflare-Roughtime ed25519 gD63hSj3ScS+wuOeGrubXlq35N1c5Lby/S+T7MNTjxo= udp roughtime.cloudflare.com:2002\n"
188
            "Google-Sandbox-Roughtime ed25519 etPaaIxcBMY1oUeGpwvPMCJMwlRVNxv51KK/tktoJTQ= udp roughtime.sandbox.google.com:2002\n"
189
            "int08h-Roughtime ed25519 AW5uAoTSTDfG5NfY1bTh08GUnOqlRb+HVhbJ3ODJvsE= udp roughtime.int08h.com:2002\n"
190
            "ticktock ed25519 cj8GsiNlRkqiDElAeNMSBBMwrAl15hYPgX50+GWX/lA= udp ticktock.mixmin.net:5333\n");
1✔
191

192
         result.confirm("size", servers.size() == 5);
2✔
193
         result.test_eq("name", servers[0].name(), "Chainpoint-Roughtime");
4✔
194
         result.test_eq("name", servers[4].name(), "ticktock");
3✔
195
         result.confirm(
3✔
196
            "public key",
197
            servers[0].public_key().get_public_key() ==
1✔
198
               Botan::Ed25519_PublicKey(Botan::base64_decode("bbT+RPS7zKX6w71ssPibzmwWqU9ffRV5oj2OresSmhE="))
3✔
199
                  .get_public_key());
200
         result.confirm("single address", servers[0].addresses().size() == 1);
2✔
201
         result.test_eq("address", servers[0].addresses()[0], "roughtime.chainpoint.org:2002");
2✔
202

203
         result.test_throws("1 field", [&]() { Botan::Roughtime::servers_from_str("A"); });
3✔
204
         result.test_throws("2 fields", [&]() { Botan::Roughtime::servers_from_str("A ed25519"); });
3✔
205
         result.test_throws("3 fields", [&]() {
2✔
206
            Botan::Roughtime::servers_from_str("A ed25519 bbT+RPS7zKX6w71ssPibzmwWqU9ffRV5oj2OresSmhE=");
1✔
207
         });
×
208
         result.test_throws("4 fields", [&]() {
2✔
209
            Botan::Roughtime::servers_from_str("A ed25519 bbT+RPS7zKX6w71ssPibzmwWqU9ffRV5oj2OresSmhE= udp");
1✔
210
         });
×
211
         result.test_throws("invalid address", [&]() {
2✔
212
            Botan::Roughtime::servers_from_str("A ed25519 bbT+RPS7zKX6w71ssPibzmwWqU9ffRV5oj2OresSmhE= udp ");
1✔
213
         });
×
214
         result.test_throws("invalid key type", [&]() {
2✔
215
            Botan::Roughtime::servers_from_str(
1✔
216
               "A rsa bbT+RPS7zKX6w71ssPibzmwWqU9ffRV5oj2OresSmhE= udp roughtime.chainpoint.org:2002");
217
         });
×
218
         result.test_throws("invalid key", [&]() {
2✔
219
            Botan::Roughtime::servers_from_str(
1✔
220
               "A ed25519 bbT+RP7zKX6w71ssPibzmwWqU9ffRV5oj2OresSmhE= udp roughtime.chainpoint.org:2002");
221
         });
×
222
         result.test_throws("invalid protocol", [&]() {
2✔
223
            Botan::Roughtime::servers_from_str(
1✔
224
               "A ed25519 bbT+RPS7zKX6w71ssPibzmwWqU9ffRV5oj2OresSmhE= tcp roughtime.chainpoint.org:2002");
225
         });
×
226

227
         return result;
1✔
228
      }
1✔
229

230
      static Test::Result test_request_online() {
1✔
231
         Test::Result result("roughtime request online");
1✔
232

233
         Botan::Roughtime::Nonce nonce(Test::rng());
1✔
234
         try {
1✔
235
            const auto response_raw =
1✔
236
               Botan::Roughtime::online_request("roughtime.cloudflare.com:2002", nonce, std::chrono::seconds(5));
1✔
237
            const auto now = std::chrono::system_clock::now();
1✔
238
            const auto response = Botan::Roughtime::Response::from_bits(response_raw, nonce);
1✔
239
            std::chrono::milliseconds local_clock_max_error(1000);
1✔
240
            const auto diff_abs =
1✔
241
               now >= response.utc_midpoint() ? now - response.utc_midpoint() : response.utc_midpoint() - now;
2✔
242
            result.confirm("online", diff_abs <= (response.utc_radius() + local_clock_max_error));
3✔
243
         } catch(const std::exception& e) {
1✔
244
            result.test_failure(e.what());
×
245
         }
×
246
         return result;
1✔
247
      }
×
248

249
   public:
250
      std::vector<Test::Result> run() override {
1✔
251
         std::vector<Test::Result> results;
1✔
252
         results.push_back(test_nonce());
2✔
253
         results.push_back(test_chain());
2✔
254
         results.push_back(test_server_information());
2✔
255

256
         if(Test::options().run_online_tests()) {
1✔
257
            results.push_back(test_request_online());
2✔
258
         }
259

260
         return results;
1✔
261
      }
×
262
};
263

264
BOTAN_REGISTER_TEST("roughtime", "roughtime_tests", Roughtime);
265

266
#endif
267

268
}  // namespace Botan_Tests
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