roughtime.googlesource.com/roughtime.git@v0.0.0-20201210012726-dd529367052d/client_test.cc (about) 1 /* Copyright 2016 The Roughtime Authors. 2 * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. */ 14 15 #include <string> 16 17 #include "gtest/gtest.h" 18 #include <openssl/curve25519.h> 19 #include <openssl/rand.h> 20 21 #include "client.h" 22 #include "open_source_fillins.h" 23 24 namespace roughtime { 25 26 TEST(CreateRequest, RequestIsValid) { 27 uint8_t nonce[kNonceLength]; 28 memset(nonce, 'a', kNonceLength); 29 30 std::string request = CreateRequest(nonce); 31 EXPECT_EQ(kMinRequestSize, request.size()); 32 Parser parser(reinterpret_cast<const uint8_t*>(request.data()), 33 request.size()); 34 ASSERT_TRUE(parser.is_valid()); 35 36 const uint8_t* request_nonce; 37 EXPECT_TRUE(parser.GetFixedLen(&request_nonce, kTagNONC, kNonceLength)); 38 EXPECT_EQ(0, memcmp(nonce, request_nonce, kNonceLength)); 39 40 const uint8_t* pad; 41 size_t pad_len; 42 EXPECT_TRUE(parser.GetTag(&pad, &pad_len, kTagPAD)); 43 EXPECT_GE(pad_len, 0); 44 } 45 46 struct ResponseBuilder { 47 uint8_t nonce[kNonceLength]; // Client's nonce. 48 49 // Delegation. 50 uint8_t delegated_private_key[ED25519_PRIVATE_KEY_LEN]; 51 uint8_t delegated_public_key[ED25519_PUBLIC_KEY_LEN]; 52 uint8_t delegation[kMinRequestSize]; 53 size_t delegation_len; 54 55 // Certificate (incorporates the delegation). 56 uint8_t root_private_key[ED25519_PRIVATE_KEY_LEN]; 57 uint8_t root_public_key[ED25519_PUBLIC_KEY_LEN]; 58 uint8_t public_key_signature[ED25519_SIGNATURE_LEN]; 59 uint8_t cert[kMinRequestSize]; 60 size_t cert_len; 61 62 // The signed portion of the response (tree root and timestamp), signed by the 63 // delegated key. 64 uint8_t tree_root[kNonceLength]; 65 uint8_t signed_response[kMinRequestSize]; 66 size_t signed_response_len; 67 68 // The final response, consisting of the signed portion, signature, Merkle 69 // tree path, and certificate. 70 uint32_t tree_index; 71 uint8_t tree_path[32 * kNonceLength]; 72 size_t tree_path_len; 73 uint8_t response[kMinRequestSize]; 74 uint8_t response_signature[ED25519_SIGNATURE_LEN]; 75 size_t response_len; 76 77 std::string out_error; 78 rough_time_t out_time; 79 uint32_t out_radius; 80 81 // Call the below functions in order to create a response. 82 ResponseBuilder(); 83 void MakeDelegation(rough_time_t mint, rough_time_t maxt); 84 void MakeDelegation() { MakeDelegation(999, 1001); } 85 void MakeCertificate(const uint8_t* private_key); 86 void MakeCertificate() { MakeCertificate(root_private_key); } 87 void MakeTree(uint32_t index); 88 void MakeTree() { MakeTree(0); } 89 void MakeSigned(rough_time_t now); 90 void MakeSigned() { MakeSigned(1000); } 91 void MakeResponse(const uint8_t* private_key); 92 void MakeResponse() { MakeResponse(delegated_private_key); } 93 bool ParseResponse(uint8_t nonce[kNonceLength]); 94 bool ParseResponse() { return ParseResponse(nonce); } 95 }; 96 97 ResponseBuilder::ResponseBuilder() { 98 memset(nonce, 'a', kNonceLength); 99 ED25519_keypair(delegated_public_key, delegated_private_key); 100 ED25519_keypair(root_public_key, root_private_key); 101 } 102 103 void ResponseBuilder::MakeDelegation(rough_time_t mint, rough_time_t maxt) { 104 Builder builder(delegation, arraysize(delegation), 3); 105 ASSERT_TRUE(builder.AddTagData(kTagPUBK, delegated_public_key, 106 arraysize(delegated_public_key))); 107 ASSERT_TRUE(builder.AddTagData( 108 kTagMINT, reinterpret_cast<const uint8_t*>(&mint), sizeof(mint))); 109 ASSERT_TRUE(builder.AddTagData( 110 kTagMAXT, reinterpret_cast<const uint8_t*>(&maxt), sizeof(maxt))); 111 ASSERT_TRUE(builder.Finish(&delegation_len)); 112 } 113 114 void ResponseBuilder::MakeCertificate(const uint8_t* private_key) { 115 size_t context_len = arraysize(kCertContextString); 116 uint8_t to_sign[kMinRequestSize]; 117 ASSERT_LE(delegation_len + context_len, sizeof(to_sign)); 118 memcpy(to_sign, kCertContextString, context_len); 119 memcpy(to_sign + context_len, delegation, delegation_len); 120 ASSERT_TRUE(ED25519_sign(public_key_signature, to_sign, 121 context_len + delegation_len, private_key)); 122 Builder builder(cert, arraysize(cert), 2); 123 ASSERT_TRUE(builder.AddTagData(kTagSIG, public_key_signature, 124 arraysize(public_key_signature))); 125 ASSERT_TRUE(builder.AddTagData(kTagDELE, delegation, delegation_len)); 126 ASSERT_TRUE(builder.Finish(&cert_len)); 127 } 128 129 void ResponseBuilder::MakeTree(uint32_t i) { 130 tree_index = i; 131 HashLeaf(tree_root, nonce); 132 for (tree_path_len = 0; i > 0; i >>= 1) { 133 const bool path_element_is_right = i & 1; 134 uint8_t* sibling = tree_path + tree_path_len; 135 RAND_bytes(sibling, kNonceLength); 136 if (path_element_is_right) { 137 HashNode(tree_root, tree_root, sibling); 138 } else { 139 HashNode(tree_root, sibling, tree_root); 140 } 141 tree_path_len += kNonceLength; 142 } 143 } 144 145 void ResponseBuilder::MakeSigned(rough_time_t now) { 146 Builder builder(signed_response, arraysize(signed_response), 3); 147 static const uint32_t kRadius = 1000000; 148 builder.AddTagData(kTagRADI, reinterpret_cast<const uint8_t*>(&kRadius), 149 sizeof(kRadius)); 150 builder.AddTagData(kTagMIDP, reinterpret_cast<const uint8_t*>(&now), 151 sizeof(now)); 152 builder.AddTagData(kTagROOT, tree_root, arraysize(tree_root)); 153 builder.Finish(&signed_response_len); 154 } 155 156 void ResponseBuilder::MakeResponse(const uint8_t* private_key) { 157 size_t context_len = arraysize(kContextString); 158 uint8_t to_sign[kMinRequestSize]; 159 ASSERT_LE(signed_response_len + context_len, sizeof(to_sign)); 160 memcpy(to_sign, kContextString, context_len); 161 memcpy(to_sign + context_len, signed_response, signed_response_len); 162 ASSERT_TRUE(ED25519_sign(response_signature, to_sign, 163 context_len + signed_response_len, private_key)); 164 Builder builder(response, arraysize(response), 5); 165 ASSERT_TRUE(builder.AddTagData(kTagSIG, response_signature, 166 arraysize(response_signature))); 167 ASSERT_TRUE(builder.AddTagData(kTagPATH, tree_path, tree_path_len)); 168 ASSERT_TRUE( 169 builder.AddTagData(kTagSREP, signed_response, signed_response_len)); 170 ASSERT_TRUE(builder.AddTagData(kTagCERT, cert, cert_len)); 171 ASSERT_TRUE(builder.AddTagData(kTagINDX, 172 reinterpret_cast<const uint8_t*>(&tree_index), 173 sizeof(tree_index))); 174 ASSERT_TRUE(builder.Finish(&response_len)); 175 } 176 177 bool ResponseBuilder::ParseResponse(uint8_t nonce[kNonceLength]) { 178 return ::roughtime::ParseResponse(&out_time, &out_radius, &out_error, 179 root_public_key, response, response_len, 180 nonce); 181 } 182 183 TEST(ParseResponse, ValidResponse) { 184 ResponseBuilder builder; 185 builder.MakeDelegation(); 186 builder.MakeCertificate(); 187 builder.MakeTree(); 188 builder.MakeSigned(); 189 builder.MakeResponse(); 190 EXPECT_TRUE(builder.ParseResponse()) << builder.out_error; 191 EXPECT_EQ(1000, builder.out_time); 192 } 193 194 TEST(ParseResponse, BadTreeRoot) { 195 ResponseBuilder builder; 196 builder.MakeDelegation(); 197 builder.MakeCertificate(); 198 builder.MakeTree(); 199 memset(builder.tree_root, 0, kNonceLength); 200 builder.MakeSigned(); 201 builder.MakeResponse(); 202 EXPECT_FALSE(builder.ParseResponse()); 203 } 204 205 TEST(ParseResponse, TestAllTreeIndices) { 206 for (uint32_t i = 0; i <= 32; i++) { 207 ResponseBuilder builder; 208 builder.MakeDelegation(); 209 builder.MakeCertificate(); 210 builder.MakeTree(i); 211 builder.MakeSigned(); 212 builder.MakeResponse(); 213 EXPECT_TRUE(builder.ParseResponse()) << "failed at index " << i; 214 EXPECT_EQ(1000, builder.out_time); 215 } 216 } 217 218 TEST(ParseResponse, WrongKeyUsedToSignResponse) { 219 ResponseBuilder builder; 220 builder.MakeDelegation(); 221 builder.MakeCertificate(); 222 builder.MakeTree(); 223 builder.MakeSigned(); 224 uint8_t garbage[ED25519_PRIVATE_KEY_LEN]; 225 memset(garbage, 0, arraysize(garbage)); 226 builder.MakeResponse(garbage); 227 EXPECT_FALSE(builder.ParseResponse()); 228 } 229 230 TEST(ParseResponse, WrongKeyUsedToSignCert) { 231 ResponseBuilder builder; 232 builder.MakeDelegation(); 233 uint8_t garbage[ED25519_PRIVATE_KEY_LEN]; 234 memset(garbage, 0, arraysize(garbage)); 235 builder.MakeCertificate(garbage); 236 builder.MakeTree(); 237 builder.MakeSigned(); 238 builder.MakeResponse(); 239 EXPECT_FALSE(builder.ParseResponse()); 240 } 241 242 TEST(ParseResponse, InvalidDelegationTimes) { 243 ResponseBuilder builder; 244 builder.MakeDelegation(1001, 999); // Order reversed. 245 builder.MakeCertificate(); 246 builder.MakeTree(); 247 builder.MakeSigned(); 248 builder.MakeResponse(); 249 EXPECT_FALSE(builder.ParseResponse()); 250 } 251 252 TEST(ParseResponse, TimeOutsideDelegation) { 253 ResponseBuilder builder; 254 builder.MakeDelegation(); 255 builder.MakeCertificate(); 256 builder.MakeTree(); 257 builder.MakeSigned(1002); // Outside bounds. 258 builder.MakeResponse(); 259 EXPECT_FALSE(builder.ParseResponse()); 260 } 261 262 TEST(ParseResponse, NonceNotInTree) { 263 ResponseBuilder builder; 264 builder.MakeDelegation(); 265 builder.MakeCertificate(); 266 builder.MakeTree(); 267 builder.MakeSigned(); 268 builder.MakeResponse(); 269 uint8_t nonce[kNonceLength]; 270 memset(nonce, 'b', arraysize(nonce)); 271 EXPECT_FALSE(builder.ParseResponse(nonce)); // Not the nonce in the request. 272 } 273 274 } // namespace roughtime