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

randombit / botan / 5079590438

25 May 2023 12:28PM UTC coverage: 92.228% (+0.5%) from 91.723%
5079590438

Pull #3502

github

Pull Request #3502: Apply clang-format to the codebase

75589 of 81959 relevant lines covered (92.23%)

12139530.51 hits per line

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

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

8
#include "cli.h"
9

10
#if defined(BOTAN_HAS_ROUGHTIME)
11

12
   #include <botan/base64.h>
13
   #include <botan/ed25519.h>
14
   #include <botan/hash.h>
15
   #include <botan/hex.h>
16
   #include <botan/rng.h>
17
   #include <botan/roughtime.h>
18
   #include <botan/internal/calendar.h>
19

20
   #include <fstream>
21
   #include <iomanip>
22

23
namespace Botan_CLI {
24

25
class RoughtimeCheck final : public Command {
26
   public:
27
      RoughtimeCheck() : Command("roughtime_check --raw-time chain-file") {}
8✔
28

29
      std::string group() const override { return "misc"; }
1✔
30

31
      std::string description() const override { return "Parse and validate Roughtime chain file"; }
1✔
32

33
      void go() override {
3✔
34
         const auto chain = Botan::Roughtime::Chain(slurp_file_as_str(get_arg("chain-file")));
9✔
35
         unsigned i = 0;
3✔
36
         for(const auto& response : chain.responses()) {
9✔
37
            output() << std::setw(3) << ++i << ": UTC ";
6✔
38
            if(flag_set("raw-time")) {
6✔
39
               output()
1✔
40
                  << Botan::Roughtime::Response::sys_microseconds64(response.utc_midpoint()).time_since_epoch().count();
1✔
41
            } else {
42
               output() << Botan::calendar_point(response.utc_midpoint()).to_string();
15✔
43
            }
44
            output() << " (+-" << Botan::Roughtime::Response::microseconds32(response.utc_radius()).count() << "us)\n";
6✔
45
         }
2✔
46
      }
2✔
47
};
48

49
BOTAN_REGISTER_COMMAND("roughtime_check", RoughtimeCheck);
4✔
50

51
class Roughtime final : public Command {
52
   public:
53
      Roughtime() :
7✔
54
            Command(
55
               "roughtime --raw-time --chain-file=roughtime-chain --max-chain-size=128 --check-local-clock=60 --host= --pubkey= --servers-file=") {
7✔
56
      }
7✔
57

58
      std::string help_text() const override {
×
59
         return Command::help_text() + R"(
×
60

61
--servers-file=<filename>
62
   List of servers that will queried in sequence.
63

64
   File contents syntax:
65
      <name> <key type> <base 64 encoded public key> <protocol> <host:port>
66

67
   Example servers:
68
      Cloudflare-Roughtime ed25519 gD63hSj3ScS+wuOeGrubXlq35N1c5Lby/S+T7MNTjxo= udp roughtime.cloudflare.com:2002
69
      Google-Sandbox-Roughtime ed25519 etPaaIxcBMY1oUeGpwvPMCJMwlRVNxv51KK/tktoJTQ= udp roughtime.sandbox.google.com:2002
70

71
--chain-file=<filename>
72
   Succesfull queries are appended to this file.
73
   If limit of --max-chain-size records is reached, the oldest records are truncated.
74
   This queries records can be replayed using command roughtime_check <chain-file>.
75

76
   File contents syntax:
77
      <key type> <base 64 encoded public key> <base 64 encoded blind or nonce> <base 64 encoded server response>
78
)";
79
      }
80

81
      std::string group() const override { return "misc"; }
1✔
82

83
      std::string description() const override { return "Retrieve time from Roughtime server"; }
1✔
84

85
      void query(std::unique_ptr<Botan::Roughtime::Chain>& chain,
5✔
86
                 const size_t max_chain_size,
87
                 const std::string& address,
88
                 const Botan::Ed25519_PublicKey& public_key) {
89
         Botan::Roughtime::Nonce nonce;
5✔
90
         Botan::Roughtime::Nonce blind;
5✔
91
         if(chain) {
5✔
92
            blind = Botan::Roughtime::Nonce(rng());
3✔
93
            nonce = chain->next_nonce(blind);
3✔
94
         } else {
95
            nonce = Botan::Roughtime::Nonce(rng());
2✔
96
         }
97
         const auto response_raw = Botan::Roughtime::online_request(address, nonce, std::chrono::seconds(5));
5✔
98
         const auto response = Botan::Roughtime::Response::from_bits(response_raw, nonce);
5✔
99
         if(flag_set("raw-time")) {
5✔
100
            output()
1✔
101
               << "UTC "
1✔
102
               << Botan::Roughtime::Response::sys_microseconds64(response.utc_midpoint()).time_since_epoch().count();
1✔
103
         } else {
104
            output() << "UTC " << Botan::calendar_point(response.utc_midpoint()).to_string();
12✔
105
         }
106
         output() << " (+-" << Botan::Roughtime::Response::microseconds32(response.utc_radius()).count() << "us)";
5✔
107
         if(!response.validate(public_key)) {
5✔
108
            error_output() << "ERROR: Public key does not match!\n";
1✔
109
            set_return_code(1);
1✔
110
            return;
1✔
111
         }
112
         const auto tolerance = get_arg_sz("check-local-clock");
4✔
113
         if(tolerance) {
4✔
114
            const auto now = std::chrono::system_clock::now();
1✔
115
            const auto diff_abs =
1✔
116
               now >= response.utc_midpoint() ? now - response.utc_midpoint() : response.utc_midpoint() - now;
2✔
117
            if(diff_abs > (response.utc_radius() + std::chrono::seconds(tolerance))) {
2✔
118
               error_output() << "ERROR: Local clock mismatch\n";
1✔
119
               set_return_code(1);
1✔
120
               return;
1✔
121
            }
122
            output() << " Local clock match";
×
123
         }
124
         if(chain)
3✔
125
            chain->append({response_raw, public_key, blind}, max_chain_size);
3✔
126
         output() << '\n';
3✔
127
      }
5✔
128

129
      void go() override {
6✔
130
         const auto max_chain_size = get_arg_sz("max-chain-size");
6✔
131
         const auto chain_file = get_arg("chain-file");
6✔
132
         const auto servers_file = get_arg_or("servers-file", "");
12✔
133
         const auto host = get_arg_or("host", "");
12✔
134
         const auto pk = get_arg_or("pubkey", "");
12✔
135

136
         std::unique_ptr<Botan::Roughtime::Chain> chain;
6✔
137
         if(!chain_file.empty() && max_chain_size >= 1) {
6✔
138
            try {
4✔
139
               chain = std::make_unique<Botan::Roughtime::Chain>(slurp_file_as_str(chain_file));
8✔
140
            } catch(const CLI_IO_Error&) {
2✔
141
               // file is to still be created
142
               chain = std::make_unique<Botan::Roughtime::Chain>();
4✔
143
            }
2✔
144
         }
145

146
         const bool from_servers_file = !servers_file.empty();
6✔
147
         const bool from_host_and_pk = !host.empty() && !pk.empty();
6✔
148
         if(from_servers_file == from_host_and_pk) {
6✔
149
            error_output() << "Please specify either --servers-file or --host and --pubkey\n";
1✔
150
            set_return_code(1);
1✔
151
            return;
1✔
152
         }
153

154
         if(!servers_file.empty()) {
5✔
155
            const auto servers = Botan::Roughtime::servers_from_str(slurp_file_as_str(servers_file));
3✔
156

157
            for(const auto& s : servers) {
6✔
158
               output() << std::setw(25) << std::left << s.name() << ": ";
6✔
159
               for(const auto& a : s.addresses()) {
3✔
160
                  try {
3✔
161
                     query(chain, max_chain_size, a, s.public_key());
3✔
162
                     break;
163
                  } catch(const std::exception& ex)  //network error, try next address
×
164
                  {
165
                     error_output() << ex.what() << '\n';
×
166
                  }
×
167
               }
168
            }
169

170
         } else {
3✔
171
            query(chain, max_chain_size, host, Botan::Ed25519_PublicKey(Botan::base64_decode(pk)));
6✔
172
         }
173

174
         if(chain) {
5✔
175
            std::ofstream out(chain_file);
3✔
176
            out << chain->to_string();
6✔
177
         }
3✔
178
      }
14✔
179
};
180

181
BOTAN_REGISTER_COMMAND("roughtime", Roughtime);
7✔
182

183
}
184

185
#endif
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