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