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 #ifndef BOTAN_ROUGHTIME_H_
9 #define BOTAN_ROUGHTIME_H_
10 
11 #include <array>
12 #include <chrono>
13 #include <vector>
14 
15 #include <botan/ed25519.h>
16 
17 namespace Botan {
18 
19 class RandomNumberGenerator;
20 
21 namespace Roughtime {
22 
23 const unsigned request_min_size = 1024;
24 
25 class BOTAN_PUBLIC_API(2, 13) Roughtime_Error final : public Decoding_Error
26    {
27    public:
Roughtime_Error(const std::string & s)28       explicit Roughtime_Error(const std::string& s) : Decoding_Error("Roughtime " + s) {}
error_type()29       ErrorType error_type() const noexcept override { return ErrorType::RoughtimeError; }
30    };
31 
32 class BOTAN_PUBLIC_API(2, 13) Nonce final
33    {
34    public:
35       Nonce() = default;
36       Nonce(const std::vector<uint8_t>& nonce);
37       Nonce(RandomNumberGenerator& rng);
Nonce(const std::array<uint8_t,64> & nonce)38       Nonce(const std::array<uint8_t, 64>& nonce)
39          {
40          m_nonce = nonce;
41          }
42       bool operator==(const Nonce& rhs) const { return m_nonce == rhs.m_nonce; }
get_nonce()43       const std::array<uint8_t, 64>& get_nonce() const { return m_nonce; }
44    private:
45       std::array<uint8_t, 64> m_nonce;
46    };
47 
48 
49 /**
50 * An Roughtime request.
51 */
52 BOTAN_PUBLIC_API(2, 13)
53 std::array<uint8_t, request_min_size> encode_request(const Nonce& nonce);
54 
55 /**
56 * An Roughtime response.
57 */
58 class BOTAN_PUBLIC_API(2, 13) Response final
59    {
60    public:
61       using microseconds32 = std::chrono::duration<uint32_t, std::micro>;
62       using microseconds64 = std::chrono::duration<uint64_t, std::micro>;
63       using sys_microseconds64 = std::chrono::time_point<std::chrono::system_clock, microseconds64>;
64 
65       static Response from_bits(const std::vector<uint8_t>& response, const Nonce& nonce);
66 
67       bool validate(const Ed25519_PublicKey& pk) const;
68 
utc_midpoint()69       sys_microseconds64 utc_midpoint() const { return m_utc_midpoint; }
70 
utc_radius()71       microseconds32 utc_radius() const { return m_utc_radius; }
72    private:
Response(const std::array<uint8_t,72> & dele,const std::array<uint8_t,64> & sig,sys_microseconds64 utc_midp,microseconds32 utc_radius)73       Response(const std::array<uint8_t, 72>& dele,
74                const std::array<uint8_t, 64>& sig,
75                sys_microseconds64 utc_midp,
76                microseconds32 utc_radius)
77          : m_cert_dele(dele)
78          , m_cert_sig(sig)
79          , m_utc_midpoint {utc_midp}
80          , m_utc_radius {utc_radius}
81          {}
82       const std::array<uint8_t, 72> m_cert_dele;
83       const std::array<uint8_t, 64> m_cert_sig;
84       const sys_microseconds64 m_utc_midpoint;
85       const microseconds32 m_utc_radius;
86    };
87 
88 class BOTAN_PUBLIC_API(2, 13) Link final
89    {
90    public:
Link(const std::vector<uint8_t> & response,const Ed25519_PublicKey & public_key,const Nonce & nonce_or_blind)91       Link(const std::vector<uint8_t>& response,
92            const Ed25519_PublicKey& public_key,
93            const Nonce& nonce_or_blind)
94          : m_response{response}
95          , m_public_key{public_key}
96          , m_nonce_or_blind{nonce_or_blind}
97          {}
response()98       const std::vector<uint8_t>& response() const { return m_response; }
public_key()99       const Ed25519_PublicKey& public_key() const { return m_public_key; }
nonce_or_blind()100       const Nonce& nonce_or_blind() const { return m_nonce_or_blind; }
nonce_or_blind()101       Nonce& nonce_or_blind() { return m_nonce_or_blind; }
102 
103    private:
104       std::vector<uint8_t> m_response;
105       Ed25519_PublicKey m_public_key;
106       Nonce m_nonce_or_blind;
107    };
108 
109 class BOTAN_PUBLIC_API(2, 13) Chain final
110    {
111    public:
112       Chain() = default; //empty
113       Chain(const std::string& str);
links()114       const std::vector<Link>& links() const { return m_links; }
115       std::vector<Response> responses() const;
116       Nonce next_nonce(const Nonce& blind) const;
117       void append(const Link& new_link, size_t max_chain_size);
118       std::string to_string() const;
119    private:
120       std::vector<Link> m_links;
121    };
122 
123 /**
124 */
125 BOTAN_PUBLIC_API(2, 13)
126 Nonce nonce_from_blind(const std::vector<uint8_t>& previous_response,
127                        const Nonce& blind);
128 
129 /**
130 * Makes an online Roughtime request via UDP and returns the Roughtime response.
131 * @param url Roughtime server UDP endpoint (host:port)
132 * @param nonce the nonce to send to the server
133 * @param timeout a timeout on the UDP request
134 * @return Roughtime response
135 */
136 BOTAN_PUBLIC_API(2, 13)
137 std::vector<uint8_t> online_request(const std::string& url,
138                                     const Nonce& nonce,
139                                     std::chrono::milliseconds timeout = std::chrono::seconds(3));
140 
141 struct BOTAN_PUBLIC_API(2, 13) Server_Information final
142    {
143 public:
Server_Informationfinal144    Server_Information(const std::string& name,
145                       const Botan::Ed25519_PublicKey& public_key,
146                       const std::vector<std::string>& addresses)
147       : m_name { name }
148       , m_public_key { public_key }
149       , m_addresses { addresses }
150       {}
namefinal151    const std::string& name() const {return m_name;}
public_keyfinal152    const Botan::Ed25519_PublicKey& public_key() const {return m_public_key;}
addressesfinal153    const std::vector<std::string>& addresses() const {return m_addresses;}
154 
155 private:
156    std::string m_name;
157    Botan::Ed25519_PublicKey m_public_key;
158    std::vector<std::string> m_addresses;
159    };
160 
161 BOTAN_PUBLIC_API(2, 13)
162 std::vector<Server_Information> servers_from_str(const std::string& str);
163 
164 }
165 }
166 
167 #endif
168