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