LCOV - code coverage report
Current view: top level - test - test_hs_descriptor.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 460 461 99.8 %
Date: 2021-11-24 03:28:48 Functions: 12 12 100.0 %

          Line data    Source code
       1             : /* Copyright (c) 2016-2021, The Tor Project, Inc. */
       2             : /* See LICENSE for licensing information */
       3             : 
       4             : /**
       5             :  * \file test_hs_descriptor.c
       6             :  * \brief Test hidden service descriptor encoding and decoding.
       7             :  */
       8             : 
       9             : #define HS_DESCRIPTOR_PRIVATE
      10             : 
      11             : #include "lib/crypt_ops/crypto_ed25519.h"
      12             : #include "lib/crypt_ops/crypto_format.h"
      13             : #include "lib/crypt_ops/crypto_digest.h"
      14             : #include "lib/crypt_ops/crypto_rand.h"
      15             : #include "trunnel/ed25519_cert.h"
      16             : #include "core/or/or.h"
      17             : #include "app/config/config.h"
      18             : #include "feature/hs/hs_descriptor.h"
      19             : #include "test/test.h"
      20             : #include "feature/nodelist/torcert.h"
      21             : 
      22             : #include "test/hs_test_helpers.h"
      23             : #include "test/test_helpers.h"
      24             : #include "test/log_test_helpers.h"
      25             : #include "test/rng_test_helpers.h"
      26             : 
      27             : #ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
      28             : DISABLE_GCC_WARNING("-Woverlength-strings")
      29             : /* We allow huge string constants in the unit tests, but not in the code
      30             :  * at large. */
      31             : #endif
      32             : #include "test_hs_descriptor.inc"
      33             : ENABLE_GCC_WARNING("-Woverlength-strings")
      34             : 
      35             : /* Test certificate encoding put in a descriptor. */
      36             : static void
      37           1 : test_cert_encoding(void *arg)
      38             : {
      39           1 :   int ret;
      40           1 :   char *encoded = NULL;
      41           1 :   ed25519_keypair_t kp;
      42           1 :   ed25519_public_key_t signed_key;
      43           1 :   ed25519_secret_key_t secret_key;
      44           1 :   tor_cert_t *cert = NULL;
      45             : 
      46           1 :   (void) arg;
      47             : 
      48             :   /* Change time to 03-01-2002 23:36 UTC */
      49           1 :   update_approx_time(1010101010);
      50           1 :   time_t now = approx_time();
      51             : 
      52           1 :   ret = ed25519_keypair_generate(&kp, 0);
      53           1 :   tt_int_op(ret, == , 0);
      54           1 :   ret = ed25519_secret_key_generate(&secret_key, 0);
      55           1 :   tt_int_op(ret, == , 0);
      56           1 :   ret = ed25519_public_key_generate(&signed_key, &secret_key);
      57           1 :   tt_int_op(ret, == , 0);
      58             : 
      59           1 :   cert = tor_cert_create_ed25519(&kp, CERT_TYPE_SIGNING_AUTH, &signed_key,
      60             :                          now, 3600 * 2, CERT_FLAG_INCLUDE_SIGNING_KEY);
      61           1 :   tt_assert(cert);
      62             : 
      63             :   /* Test the certificate encoding function. */
      64           1 :   ret = tor_cert_encode_ed22519(cert, &encoded);
      65           1 :   tt_int_op(ret, OP_EQ, 0);
      66             : 
      67             :   /* Validated the certificate string. */
      68             :   {
      69           1 :     char *end, *pos = encoded;
      70           1 :     char *b64_cert, buf[256];
      71           1 :     size_t b64_cert_len;
      72           1 :     tor_cert_t *parsed_cert;
      73             : 
      74           1 :     tt_int_op(strcmpstart(pos, "-----BEGIN ED25519 CERT-----\n"), OP_EQ, 0);
      75           1 :     pos += strlen("-----BEGIN ED25519 CERT-----\n");
      76             : 
      77             :     /* Isolate the base64 encoded certificate and try to decode it. */
      78           1 :     end = strstr(pos, "-----END ED25519 CERT-----");
      79           1 :     tt_assert(end);
      80           1 :     b64_cert = pos;
      81           1 :     b64_cert_len = end - pos;
      82           1 :     ret = base64_decode(buf, sizeof(buf), b64_cert, b64_cert_len);
      83           1 :     tt_int_op(ret, OP_GT, 0);
      84             :     /* Parseable? */
      85           1 :     parsed_cert = tor_cert_parse((uint8_t *) buf, ret);
      86           1 :     tt_assert(parsed_cert);
      87             :     /* Signature is valid? */
      88           1 :     ret = tor_cert_checksig(parsed_cert, &kp.pubkey, now + 10);
      89           1 :     tt_int_op(ret, OP_EQ, 0);
      90           1 :     ret = tor_cert_eq(cert, parsed_cert);
      91           1 :     tt_int_op(ret, OP_EQ, 1);
      92             :     /* The cert did have the signing key? */
      93           1 :     ret= ed25519_pubkey_eq(&parsed_cert->signing_key, &kp.pubkey);
      94           1 :     tt_int_op(ret, OP_EQ, 1);
      95             : 
      96             :     /* Get to the end part of the certificate. */
      97           1 :     pos += b64_cert_len;
      98           1 :     tt_int_op(strcmpstart(pos, "-----END ED25519 CERT-----"), OP_EQ, 0);
      99           1 :     pos += strlen("-----END ED25519 CERT-----");
     100           1 :     tt_str_op(pos, OP_EQ, "");
     101             : 
     102             :     /* Check that certificate expiry works properly and emits the right log
     103             :        message */
     104           1 :     const char *msg = "fire";
     105             :     /* Move us forward 4 hours so that the the certificate is definitely
     106             :        expired */
     107           1 :     update_approx_time(approx_time() + 3600*4);
     108           1 :     setup_full_capture_of_logs(LOG_PROTOCOL_WARN);
     109           1 :     ret = cert_is_valid(parsed_cert, CERT_TYPE_SIGNING_AUTH, msg);
     110           1 :     tt_int_op(ret, OP_EQ, 0);
     111             :     /* Since the current time at the creation of the cert was "03-01-2002
     112             :      * 23:36", and the expiration date of the cert was two hours, the Tor code
     113             :      * will ceiling that and make it 02:00. Make sure that the right log
     114             :      * message is emitted */
     115           1 :     expect_log_msg_containing("Invalid signature for fire: expired"
     116           1 :                               " (2002-01-04 02:00:00)");
     117           1 :     teardown_capture_of_logs();
     118             : 
     119           1 :     tor_cert_free(parsed_cert);
     120             :   }
     121             : 
     122           1 :  done:
     123           1 :   tor_cert_free(cert);
     124           1 :   tor_free(encoded);
     125           1 : }
     126             : 
     127             : /* Test the descriptor padding. */
     128             : static void
     129           1 : test_descriptor_padding(void *arg)
     130             : {
     131           1 :   char *plaintext;
     132           1 :   size_t plaintext_len, padded_len;
     133           1 :   uint8_t *padded_plaintext = NULL;
     134             : 
     135             : /* Example: if l = 129, the ceiled division gives 2 and then multiplied by 128
     136             :  * to give 256. With l = 127, ceiled division gives 1 then times 128. */
     137             : #define PADDING_EXPECTED_LEN(l) \
     138             :   CEIL_DIV(l, HS_DESC_SUPERENC_PLAINTEXT_PAD_MULTIPLE) * \
     139             :   HS_DESC_SUPERENC_PLAINTEXT_PAD_MULTIPLE
     140             : 
     141           1 :   (void) arg;
     142             : 
     143             :   { /* test #1: no padding */
     144           1 :     plaintext_len = HS_DESC_SUPERENC_PLAINTEXT_PAD_MULTIPLE;
     145           1 :     plaintext = tor_malloc(plaintext_len);
     146           1 :     padded_len = build_plaintext_padding(plaintext, plaintext_len,
     147             :                                          &padded_plaintext);
     148           1 :     tt_assert(padded_plaintext);
     149           1 :     tor_free(plaintext);
     150             :     /* Make sure our padding has been zeroed. */
     151           1 :     tt_int_op(fast_mem_is_zero((char *) padded_plaintext + plaintext_len,
     152             :                               padded_len - plaintext_len), OP_EQ, 1);
     153           1 :     tor_free(padded_plaintext);
     154             :     /* Never never have a padded length smaller than the plaintext. */
     155           1 :     tt_int_op(padded_len, OP_GE, plaintext_len);
     156           1 :     tt_int_op(padded_len, OP_EQ, PADDING_EXPECTED_LEN(plaintext_len));
     157             :   }
     158             : 
     159             :   { /* test #2: one byte padding? */
     160           1 :     plaintext_len = HS_DESC_SUPERENC_PLAINTEXT_PAD_MULTIPLE - 1;
     161           1 :     plaintext = tor_malloc(plaintext_len);
     162           1 :     padded_plaintext = NULL;
     163           1 :     padded_len = build_plaintext_padding(plaintext, plaintext_len,
     164             :                                          &padded_plaintext);
     165           1 :     tt_assert(padded_plaintext);
     166           1 :     tor_free(plaintext);
     167             :     /* Make sure our padding has been zeroed. */
     168           1 :     tt_int_op(fast_mem_is_zero((char *) padded_plaintext + plaintext_len,
     169             :                               padded_len - plaintext_len), OP_EQ, 1);
     170           1 :     tor_free(padded_plaintext);
     171             :     /* Never never have a padded length smaller than the plaintext. */
     172           1 :     tt_int_op(padded_len, OP_GE, plaintext_len);
     173           1 :     tt_int_op(padded_len, OP_EQ, PADDING_EXPECTED_LEN(plaintext_len));
     174             :   }
     175             : 
     176             :   { /* test #3: Lots more bytes of padding? */
     177           1 :     plaintext_len = HS_DESC_SUPERENC_PLAINTEXT_PAD_MULTIPLE + 1;
     178           1 :     plaintext = tor_malloc(plaintext_len);
     179           1 :     padded_plaintext = NULL;
     180           1 :     padded_len = build_plaintext_padding(plaintext, plaintext_len,
     181             :                                          &padded_plaintext);
     182           1 :     tt_assert(padded_plaintext);
     183           1 :     tor_free(plaintext);
     184             :     /* Make sure our padding has been zeroed. */
     185           1 :     tt_int_op(fast_mem_is_zero((char *) padded_plaintext + plaintext_len,
     186             :                               padded_len - plaintext_len), OP_EQ, 1);
     187           1 :     tor_free(padded_plaintext);
     188             :     /* Never never have a padded length smaller than the plaintext. */
     189           1 :     tt_int_op(padded_len, OP_GE, plaintext_len);
     190           1 :     tt_int_op(padded_len, OP_EQ, PADDING_EXPECTED_LEN(plaintext_len));
     191             :   }
     192             : 
     193           1 :  done:
     194           1 :   return;
     195             : }
     196             : 
     197             : static void
     198           1 : test_encode_descriptor(void *arg)
     199             : {
     200           1 :   int ret;
     201           1 :   ed25519_keypair_t signing_kp;
     202           1 :   hs_descriptor_t *desc = NULL;
     203             : 
     204           1 :   (void) arg;
     205             : 
     206           1 :   ret = ed25519_keypair_generate(&signing_kp, 0);
     207           1 :   tt_int_op(ret, OP_EQ, 0);
     208           1 :   desc = hs_helper_build_hs_desc_with_ip(&signing_kp);
     209             : 
     210             :   {
     211           1 :     char *encoded = NULL;
     212           1 :     ret = hs_desc_encode_descriptor(desc, &signing_kp, NULL, &encoded);
     213           1 :     tt_int_op(ret, OP_EQ, 0);
     214           1 :     tt_assert(encoded);
     215             : 
     216           1 :     tor_free(encoded);
     217             :   }
     218             : 
     219             :   {
     220           1 :     char *encoded = NULL;
     221           1 :     uint8_t descriptor_cookie[HS_DESC_DESCRIPTOR_COOKIE_LEN];
     222             : 
     223           1 :     crypto_strongest_rand(descriptor_cookie, sizeof(descriptor_cookie));
     224             : 
     225           1 :     ret = hs_desc_encode_descriptor(desc, &signing_kp,
     226             :                                    descriptor_cookie, &encoded);
     227           1 :     tt_int_op(ret, OP_EQ, 0);
     228           1 :     tt_assert(encoded);
     229             : 
     230           1 :     tor_free(encoded);
     231             :   }
     232           1 :  done:
     233           1 :   hs_descriptor_free(desc);
     234           1 : }
     235             : 
     236             : static void
     237           1 : test_decode_descriptor(void *arg)
     238             : {
     239           1 :   int ret;
     240           1 :   int i;
     241           1 :   char *encoded = NULL;
     242           1 :   ed25519_keypair_t signing_kp;
     243           1 :   hs_descriptor_t *desc = NULL;
     244           1 :   hs_descriptor_t *decoded = NULL;
     245           1 :   hs_descriptor_t *desc_no_ip = NULL;
     246           1 :   hs_subcredential_t subcredential;
     247             : 
     248           1 :   (void) arg;
     249             : 
     250           1 :   ret = ed25519_keypair_generate(&signing_kp, 0);
     251           1 :   tt_int_op(ret, OP_EQ, 0);
     252           1 :   desc = hs_helper_build_hs_desc_with_ip(&signing_kp);
     253             : 
     254           1 :   hs_helper_get_subcred_from_identity_keypair(&signing_kp,
     255             :                                               &subcredential);
     256             : 
     257             :   /* Give some bad stuff to the decoding function. */
     258           1 :   ret = hs_desc_decode_descriptor("hladfjlkjadf", &subcredential,
     259             :                                   NULL, &decoded);
     260           1 :   tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
     261             : 
     262           1 :   ret = hs_desc_encode_descriptor(desc, &signing_kp, NULL, &encoded);
     263           1 :   tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
     264           1 :   tt_assert(encoded);
     265             : 
     266           1 :   ret = hs_desc_decode_descriptor(encoded, &subcredential, NULL, &decoded);
     267           1 :   tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
     268           1 :   tt_assert(decoded);
     269             : 
     270           1 :   hs_helper_desc_equal(desc, decoded);
     271             : 
     272             :   /* Decode a descriptor with _no_ introduction points. */
     273             :   {
     274           1 :     ed25519_keypair_t signing_kp_no_ip;
     275           1 :     ret = ed25519_keypair_generate(&signing_kp_no_ip, 0);
     276           1 :     tt_int_op(ret, OP_EQ, 0);
     277           1 :     hs_helper_get_subcred_from_identity_keypair(&signing_kp_no_ip,
     278             :                                                 &subcredential);
     279           1 :     desc_no_ip = hs_helper_build_hs_desc_no_ip(&signing_kp_no_ip);
     280           1 :     tt_assert(desc_no_ip);
     281           1 :     tor_free(encoded);
     282           1 :     ret = hs_desc_encode_descriptor(desc_no_ip, &signing_kp_no_ip,
     283             :                                     NULL, &encoded);
     284           1 :     tt_int_op(ret, OP_EQ, 0);
     285           1 :     tt_assert(encoded);
     286           1 :     hs_descriptor_free(decoded);
     287           1 :     ret = hs_desc_decode_descriptor(encoded, &subcredential, NULL, &decoded);
     288           1 :     tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
     289           1 :     tt_assert(decoded);
     290             :   }
     291             : 
     292             :   /* Decode a descriptor with auth clients. */
     293             :   {
     294           1 :     uint8_t descriptor_cookie[HS_DESC_DESCRIPTOR_COOKIE_LEN];
     295           1 :     curve25519_keypair_t auth_ephemeral_kp;
     296           1 :     curve25519_keypair_t client_kp, invalid_client_kp;
     297           1 :     smartlist_t *clients;
     298           1 :     hs_desc_authorized_client_t *client, *fake_client;
     299           1 :     client = tor_malloc_zero(sizeof(hs_desc_authorized_client_t));
     300             : 
     301             :     /* Prepare all the keys needed to build the auth client. */
     302           1 :     curve25519_keypair_generate(&auth_ephemeral_kp, 0);
     303           1 :     curve25519_keypair_generate(&client_kp, 0);
     304           1 :     curve25519_keypair_generate(&invalid_client_kp, 0);
     305           1 :     crypto_strongest_rand(descriptor_cookie, HS_DESC_DESCRIPTOR_COOKIE_LEN);
     306             : 
     307           1 :     memcpy(&desc->superencrypted_data.auth_ephemeral_pubkey,
     308             :            &auth_ephemeral_kp.pubkey, CURVE25519_PUBKEY_LEN);
     309             : 
     310           1 :     hs_helper_get_subcred_from_identity_keypair(&signing_kp,
     311             :                                                 &subcredential);
     312             : 
     313             :     /* Build and add the auth client to the descriptor. */
     314           1 :     clients = desc->superencrypted_data.clients;
     315           1 :     if (!clients) {
     316           0 :       clients = smartlist_new();
     317             :     }
     318           1 :     hs_desc_build_authorized_client(&subcredential,
     319             :                                     &client_kp.pubkey,
     320             :                                     &auth_ephemeral_kp.seckey,
     321             :                                     descriptor_cookie, client);
     322           1 :     smartlist_add(clients, client);
     323             : 
     324             :     /* We need to add fake auth clients here. */
     325          17 :     for (i=0; i < 15; ++i) {
     326          15 :       fake_client = hs_desc_build_fake_authorized_client();
     327          15 :       smartlist_add(clients, fake_client);
     328             :     }
     329           1 :     desc->superencrypted_data.clients = clients;
     330             : 
     331             :     /* Test the encoding/decoding in the following lines. */
     332           1 :     tor_free(encoded);
     333           1 :     ret = hs_desc_encode_descriptor(desc, &signing_kp,
     334             :                                     descriptor_cookie, &encoded);
     335           1 :     tt_int_op(ret, OP_EQ, 0);
     336           1 :     tt_assert(encoded);
     337             : 
     338             :     /* If we do not have the client secret key, the decoding must fail. */
     339           1 :     hs_descriptor_free(decoded);
     340           1 :     ret = hs_desc_decode_descriptor(encoded, &subcredential,
     341             :                                     NULL, &decoded);
     342           1 :     tt_int_op(ret, OP_EQ, HS_DESC_DECODE_NEED_CLIENT_AUTH);
     343           1 :     tt_assert(!decoded);
     344             : 
     345             :     /* If we have an invalid client secret key, the decoding must fail. */
     346           1 :     hs_descriptor_free(decoded);
     347           1 :     ret = hs_desc_decode_descriptor(encoded, &subcredential,
     348             :                                     &invalid_client_kp.seckey, &decoded);
     349           1 :     tt_int_op(ret, OP_EQ, HS_DESC_DECODE_BAD_CLIENT_AUTH);
     350           1 :     tt_assert(!decoded);
     351             : 
     352             :     /* If we have the client secret key, the decoding must succeed and the
     353             :      * decoded descriptor must be correct. */
     354           1 :     ret = hs_desc_decode_descriptor(encoded, &subcredential,
     355             :                                     &client_kp.seckey, &decoded);
     356           1 :     tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
     357           1 :     tt_assert(decoded);
     358             : 
     359           1 :     hs_helper_desc_equal(desc, decoded);
     360             :   }
     361             : 
     362           1 :  done:
     363           1 :   hs_descriptor_free(desc);
     364           1 :   hs_descriptor_free(desc_no_ip);
     365           1 :   hs_descriptor_free(decoded);
     366           1 :   tor_free(encoded);
     367           1 : }
     368             : 
     369             : static void
     370           1 : test_supported_version(void *arg)
     371             : {
     372           1 :   int ret;
     373             : 
     374           1 :   (void) arg;
     375             : 
     376             :   /* Unsupported. */
     377           1 :   ret = hs_desc_is_supported_version(42);
     378           1 :   tt_int_op(ret, OP_EQ, 0);
     379             :   /* To early. */
     380           1 :   ret = hs_desc_is_supported_version(HS_DESC_SUPPORTED_FORMAT_VERSION_MIN - 1);
     381           1 :   tt_int_op(ret, OP_EQ, 0);
     382             :   /* One too new. */
     383           1 :   ret = hs_desc_is_supported_version(HS_DESC_SUPPORTED_FORMAT_VERSION_MAX + 1);
     384           1 :   tt_int_op(ret, OP_EQ, 0);
     385             :   /* Valid version. */
     386           1 :   ret = hs_desc_is_supported_version(3);
     387           1 :   tt_int_op(ret, OP_EQ, 1);
     388             : 
     389           1 :  done:
     390           1 :   ;
     391           1 : }
     392             : 
     393             : static void
     394           1 : test_encrypted_data_len(void *arg)
     395             : {
     396           1 :   int ret;
     397           1 :   size_t value;
     398             : 
     399           1 :   (void) arg;
     400             : 
     401             :   /* No length, error. */
     402           1 :   ret = encrypted_data_length_is_valid(0);
     403           1 :   tt_int_op(ret, OP_EQ, 0);
     404             :   /* Valid value. */
     405           1 :   value = HS_DESC_ENCRYPTED_SALT_LEN + DIGEST256_LEN + 1;
     406           1 :   ret = encrypted_data_length_is_valid(value);
     407           1 :   tt_int_op(ret, OP_EQ, 1);
     408             : 
     409           1 :  done:
     410           1 :   ;
     411           1 : }
     412             : 
     413             : static void
     414           1 : test_decode_invalid_intro_point(void *arg)
     415             : {
     416           1 :   int ret;
     417           1 :   char *encoded_ip = NULL;
     418           1 :   size_t len_out;
     419           1 :   hs_desc_intro_point_t *ip = NULL;
     420           1 :   ed25519_keypair_t signing_kp;
     421           1 :   hs_descriptor_t *desc = NULL;
     422             : 
     423           1 :   (void) arg;
     424             : 
     425             :   /* Separate pieces of a valid encoded introduction point. */
     426           1 :   const char *intro_point =
     427             :     "introduction-point AQIUMDI5OUYyNjhGQ0E5RDU1Q0QxNTc=";
     428           1 :   const char *auth_key =
     429             :     "auth-key\n"
     430             :     "-----BEGIN ED25519 CERT-----\n"
     431             :     "AQkACOhAAQW8ltYZMIWpyrfyE/b4Iyi8CNybCwYs6ADk7XfBaxsFAQAgBAD3/BE4\n"
     432             :     "XojGE/N2bW/wgnS9r2qlrkydGyuCKIGayYx3haZ39LD4ZTmSMRxwmplMAqzG/XNP\n"
     433             :     "0Kkpg4p2/VnLFJRdU1SMFo1lgQ4P0bqw7Tgx200fulZ4KUM5z5V7m+a/mgY=\n"
     434             :     "-----END ED25519 CERT-----";
     435           1 :   const char *enc_key =
     436             :     "enc-key ntor bpZKLsuhxP6woDQ3yVyjm5gUKSk7RjfAijT2qrzbQk0=";
     437           1 :   const char *enc_key_cert =
     438             :     "enc-key-cert\n"
     439             :     "-----BEGIN ED25519 CERT-----\n"
     440             :     "AQsACOhZAUpNvCZ1aJaaR49lS6MCdsVkhVGVrRqoj0Y2T4SzroAtAQAgBABFOcGg\n"
     441             :     "lbTt1DF5nKTE/gU3Fr8ZtlCIOhu1A+F5LM7fqCUupfesg0KTHwyIZOYQbJuM5/he\n"
     442             :     "/jDNyLy9woPJdjkxywaY2RPUxGjLYtMQV0E8PUxWyICV+7y52fTCYaKpYQw=\n"
     443             :     "-----END ED25519 CERT-----";
     444             : 
     445             :   /* Try to decode a junk string. */
     446             :   {
     447           1 :     hs_descriptor_free(desc);
     448           1 :     desc = NULL;
     449           1 :     ret = ed25519_keypair_generate(&signing_kp, 0);
     450           1 :     tt_int_op(ret, OP_EQ, 0);
     451           1 :     desc = hs_helper_build_hs_desc_with_ip(&signing_kp);
     452           1 :     const char *junk = "this is not a descriptor";
     453           1 :     ip = decode_introduction_point(desc, junk);
     454           1 :     tt_ptr_op(ip, OP_EQ, NULL);
     455           1 :     hs_desc_intro_point_free(ip);
     456           1 :     ip = NULL;
     457             :   }
     458             : 
     459             :   /* Invalid link specifiers. */
     460             :   {
     461           1 :     smartlist_t *lines = smartlist_new();
     462           1 :     const char *bad_line = "introduction-point blah";
     463           1 :     smartlist_add(lines, (char *) bad_line);
     464           1 :     smartlist_add(lines, (char *) auth_key);
     465           1 :     smartlist_add(lines, (char *) enc_key);
     466           1 :     smartlist_add(lines, (char *) enc_key_cert);
     467           1 :     encoded_ip = smartlist_join_strings(lines, "\n", 0, &len_out);
     468           1 :     tt_assert(encoded_ip);
     469           1 :     ip = decode_introduction_point(desc, encoded_ip);
     470           1 :     tt_ptr_op(ip, OP_EQ, NULL);
     471           1 :     tor_free(encoded_ip);
     472           1 :     smartlist_free(lines);
     473           1 :     hs_desc_intro_point_free(ip);
     474           1 :     ip = NULL;
     475             :   }
     476             : 
     477             :   /* Invalid auth key type. */
     478             :   {
     479           1 :     smartlist_t *lines = smartlist_new();
     480             :     /* Try to put a valid object that our tokenize function will be able to
     481             :      * parse but that has nothing to do with the auth_key. */
     482           1 :     const char *bad_line =
     483             :       "auth-key\n"
     484             :       "-----BEGIN UNICORN CERT-----\n"
     485             :       "MIGJAoGBAO4bATcW8kW4h6RQQAKEgg+aXCpF4JwbcO6vGZtzXTDB+HdPVQzwqkbh\n"
     486             :       "XzFM6VGArhYw4m31wcP1Z7IwULir7UMnAFd7Zi62aYfU6l+Y1yAoZ1wzu1XBaAMK\n"
     487             :       "ejpwQinW9nzJn7c2f69fVke3pkhxpNdUZ+vplSA/l9iY+y+v+415AgMBAAE=\n"
     488             :       "-----END UNICORN CERT-----";
     489             :     /* Build intro point text. */
     490           1 :     smartlist_add(lines, (char *) intro_point);
     491           1 :     smartlist_add(lines, (char *) bad_line);
     492           1 :     smartlist_add(lines, (char *) enc_key);
     493           1 :     smartlist_add(lines, (char *) enc_key_cert);
     494           1 :     encoded_ip = smartlist_join_strings(lines, "\n", 0, &len_out);
     495           1 :     tt_assert(encoded_ip);
     496           1 :     ip = decode_introduction_point(desc, encoded_ip);
     497           1 :     tt_ptr_op(ip, OP_EQ, NULL);
     498           1 :     tor_free(encoded_ip);
     499           1 :     smartlist_free(lines);
     500             :   }
     501             : 
     502             :   /* Invalid enc-key. */
     503             :   {
     504           1 :     smartlist_t *lines = smartlist_new();
     505           1 :     const char *bad_line =
     506             :       "enc-key unicorn bpZKLsuhxP6woDQ3yVyjm5gUKSk7RjfAijT2qrzbQk0=";
     507             :     /* Build intro point text. */
     508           1 :     smartlist_add(lines, (char *) intro_point);
     509           1 :     smartlist_add(lines, (char *) auth_key);
     510           1 :     smartlist_add(lines, (char *) bad_line);
     511           1 :     smartlist_add(lines, (char *) enc_key_cert);
     512           1 :     encoded_ip = smartlist_join_strings(lines, "\n", 0, &len_out);
     513           1 :     tt_assert(encoded_ip);
     514           1 :     ip = decode_introduction_point(desc, encoded_ip);
     515           1 :     tt_ptr_op(ip, OP_EQ, NULL);
     516           1 :     tor_free(encoded_ip);
     517           1 :     smartlist_free(lines);
     518             :   }
     519             : 
     520             :   /* Invalid enc-key object. */
     521             :   {
     522           1 :     smartlist_t *lines = smartlist_new();
     523           1 :     const char *bad_line = "enc-key ntor";
     524             :     /* Build intro point text. */
     525           1 :     smartlist_add(lines, (char *) intro_point);
     526           1 :     smartlist_add(lines, (char *) auth_key);
     527           1 :     smartlist_add(lines, (char *) bad_line);
     528           1 :     smartlist_add(lines, (char *) enc_key_cert);
     529           1 :     encoded_ip = smartlist_join_strings(lines, "\n", 0, &len_out);
     530           1 :     tt_assert(encoded_ip);
     531           1 :     ip = decode_introduction_point(desc, encoded_ip);
     532           1 :     tt_ptr_op(ip, OP_EQ, NULL);
     533           1 :     tor_free(encoded_ip);
     534           1 :     smartlist_free(lines);
     535             :   }
     536             : 
     537             :   /* Invalid enc-key base64 curv25519 key. */
     538             :   {
     539           1 :     smartlist_t *lines = smartlist_new();
     540           1 :     const char *bad_line = "enc-key ntor blah===";
     541             :     /* Build intro point text. */
     542           1 :     smartlist_add(lines, (char *) intro_point);
     543           1 :     smartlist_add(lines, (char *) auth_key);
     544           1 :     smartlist_add(lines, (char *) bad_line);
     545           1 :     smartlist_add(lines, (char *) enc_key_cert);
     546           1 :     encoded_ip = smartlist_join_strings(lines, "\n", 0, &len_out);
     547           1 :     tt_assert(encoded_ip);
     548           1 :     ip = decode_introduction_point(desc, encoded_ip);
     549           1 :     tt_ptr_op(ip, OP_EQ, NULL);
     550           1 :     tor_free(encoded_ip);
     551           1 :     smartlist_free(lines);
     552             :   }
     553             : 
     554             :   /* Invalid enc-key invalid legacy. */
     555             :   {
     556           1 :     smartlist_t *lines = smartlist_new();
     557           1 :     const char *bad_line = "legacy-key blah===";
     558             :     /* Build intro point text. */
     559           1 :     smartlist_add(lines, (char *) intro_point);
     560           1 :     smartlist_add(lines, (char *) auth_key);
     561           1 :     smartlist_add(lines, (char *) bad_line);
     562           1 :     smartlist_add(lines, (char *) enc_key_cert);
     563           1 :     encoded_ip = smartlist_join_strings(lines, "\n", 0, &len_out);
     564           1 :     tt_assert(encoded_ip);
     565           1 :     ip = decode_introduction_point(desc, encoded_ip);
     566           1 :     tt_ptr_op(ip, OP_EQ, NULL);
     567           1 :     tor_free(encoded_ip);
     568           1 :     smartlist_free(lines);
     569             :   }
     570             : 
     571           1 :  done:
     572           1 :   hs_descriptor_free(desc);
     573           1 :   hs_desc_intro_point_free(ip);
     574           1 : }
     575             : 
     576             : /** Make sure we fail gracefully when decoding the bad desc from #23233. */
     577             : static void
     578           1 : test_decode_bad_signature(void *arg)
     579             : {
     580           1 :   hs_desc_plaintext_data_t desc_plaintext;
     581           1 :   int ret;
     582             : 
     583           1 :   (void) arg;
     584             : 
     585           1 :   memset(&desc_plaintext, 0, sizeof(desc_plaintext));
     586             : 
     587             :   /* Update approx time to dodge cert expiration */
     588           1 :   update_approx_time(1502661599);
     589             : 
     590           1 :   setup_full_capture_of_logs(LOG_WARN);
     591           1 :   ret = hs_desc_decode_plaintext(HS_DESC_BAD_SIG, &desc_plaintext);
     592           1 :   tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
     593           1 :   expect_log_msg_containing("Malformed signature line. Rejecting.");
     594           1 :   teardown_capture_of_logs();
     595             : 
     596           1 :  done:
     597           1 :   hs_desc_plaintext_data_free_contents(&desc_plaintext);
     598           1 : }
     599             : 
     600             : static void
     601           1 : test_decode_plaintext(void *arg)
     602             : {
     603           1 :   int ret;
     604           1 :   hs_desc_plaintext_data_t desc_plaintext;
     605           1 :   const char *bad_value = "unicorn";
     606             : 
     607           1 :   (void) arg;
     608             : 
     609             : #define template \
     610             :     "hs-descriptor %s\n" \
     611             :     "descriptor-lifetime %s\n" \
     612             :     "descriptor-signing-key-cert\n" \
     613             :     "-----BEGIN ED25519 CERT-----\n" \
     614             :     "AQgABjvPAQaG3g+dc6oV/oJV4ODAtkvx56uBnPtBT9mYVuHVOhn7AQAgBABUg3mQ\n" \
     615             :     "myBr4bu5LCr53wUEbW2EXui01CbUgU7pfo9LvJG3AcXRojj6HlfsUs9BkzYzYdjF\n" \
     616             :     "A69Apikgu0ewHYkFFASt7Il+gB3w6J8YstQJZT7dtbtl+doM7ug8B68Qdg8=\n" \
     617             :     "-----END ED25519 CERT-----\n" \
     618             :     "revision-counter %s\n" \
     619             :     "encrypted\n" \
     620             :     "-----BEGIN %s-----\n" \
     621             :     "UNICORN\n" \
     622             :     "-----END MESSAGE-----\n" \
     623             :     "signature m20WJH5agqvwhq7QeuEZ1mYyPWQDO+eJOZUjLhAiKu8DbL17DsDfJE6kXbWy" \
     624             :     "HimbNj2we0enV3cCOOAsmPOaAw\n"
     625             : 
     626             :   /* Invalid version. */
     627             :   {
     628           1 :     char *plaintext;
     629           1 :     tor_asprintf(&plaintext, template, bad_value, "180", "42", "MESSAGE");
     630           1 :     ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
     631           1 :     tor_free(plaintext);
     632           1 :     tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
     633             :   }
     634             : 
     635             :   /* Missing fields. */
     636             :   {
     637           1 :     const char *plaintext = "hs-descriptor 3\n";
     638           1 :     ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
     639           1 :     tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
     640             :   }
     641             : 
     642             :   /* Max length. */
     643             :   {
     644           1 :     size_t big = 64000;
     645             :     /* Must always be bigger than HS_DESC_MAX_LEN. */
     646           1 :     tt_int_op(HS_DESC_MAX_LEN, OP_LT, big);
     647           1 :     char *plaintext = tor_malloc_zero(big);
     648           1 :     memset(plaintext, 'a', big);
     649           1 :     plaintext[big - 1] = '\0';
     650           1 :     ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
     651           1 :     tor_free(plaintext);
     652           1 :     tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
     653             :   }
     654             : 
     655             :   /* Bad lifetime value. */
     656             :   {
     657           1 :     char *plaintext;
     658           1 :     tor_asprintf(&plaintext, template, "3", bad_value, "42", "MESSAGE");
     659           1 :     ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
     660           1 :     tor_free(plaintext);
     661           1 :     tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
     662             :   }
     663             : 
     664             :   /* Huge lifetime value. */
     665             :   {
     666           1 :     char *plaintext;
     667           1 :     tor_asprintf(&plaintext, template, "3", "7181615", "42", "MESSAGE");
     668           1 :     ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
     669           1 :     tor_free(plaintext);
     670           1 :     tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
     671             :   }
     672             : 
     673             :   /* Invalid encrypted section. */
     674             :   {
     675           1 :     char *plaintext;
     676           1 :     tor_asprintf(&plaintext, template, "3", "180", "42", bad_value);
     677           1 :     ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
     678           1 :     tor_free(plaintext);
     679           1 :     tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
     680             :   }
     681             : 
     682             :   /* Invalid revision counter. */
     683             :   {
     684           1 :     char *plaintext;
     685           1 :     tor_asprintf(&plaintext, template, "3", "180", bad_value, "MESSAGE");
     686           1 :     ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
     687           1 :     tor_free(plaintext);
     688           1 :     tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
     689             :   }
     690             : 
     691           1 :  done:
     692           1 :   ;
     693           1 : }
     694             : 
     695             : static void
     696           1 : test_validate_cert(void *arg)
     697             : {
     698           1 :   int ret;
     699           1 :   time_t now = time(NULL);
     700           1 :   ed25519_keypair_t kp;
     701           1 :   tor_cert_t *cert = NULL;
     702             : 
     703           1 :   (void) arg;
     704             : 
     705           1 :   ret = ed25519_keypair_generate(&kp, 0);
     706           1 :   tt_int_op(ret, OP_EQ, 0);
     707             : 
     708             :   /* Cert of type CERT_TYPE_AUTH_HS_IP_KEY. */
     709           1 :   cert = tor_cert_create_ed25519(&kp, CERT_TYPE_AUTH_HS_IP_KEY,
     710             :                                      &kp.pubkey, now, 3600,
     711             :                                      CERT_FLAG_INCLUDE_SIGNING_KEY);
     712           1 :   tt_assert(cert);
     713             :   /* Test with empty certificate. */
     714           1 :   ret = cert_is_valid(NULL, CERT_TYPE_AUTH_HS_IP_KEY, "unicorn");
     715           1 :   tt_int_op(ret, OP_EQ, 0);
     716             :   /* Test with a bad type. */
     717           1 :   ret = cert_is_valid(cert, CERT_TYPE_SIGNING_HS_DESC, "unicorn");
     718           1 :   tt_int_op(ret, OP_EQ, 0);
     719             :   /* Normal validation. */
     720           1 :   ret = cert_is_valid(cert, CERT_TYPE_AUTH_HS_IP_KEY, "unicorn");
     721           1 :   tt_int_op(ret, OP_EQ, 1);
     722             :   /* Break signing key so signature verification will fails. */
     723           1 :   memset(&cert->signing_key, 0, sizeof(cert->signing_key));
     724           1 :   ret = cert_is_valid(cert, CERT_TYPE_AUTH_HS_IP_KEY, "unicorn");
     725           1 :   tt_int_op(ret, OP_EQ, 0);
     726           1 :   tor_cert_free(cert);
     727             : 
     728             :   /* Try a cert without including the signing key. */
     729           1 :   cert = tor_cert_create_ed25519(&kp, CERT_TYPE_AUTH_HS_IP_KEY,
     730             :                                  &kp.pubkey, now, 3600, 0);
     731             : 
     732           1 :   tt_assert(cert);
     733             :   /* Test with a bad type. */
     734           1 :   ret = cert_is_valid(cert, CERT_TYPE_AUTH_HS_IP_KEY, "unicorn");
     735           1 :   tt_int_op(ret, OP_EQ, 0);
     736             : 
     737           1 :  done:
     738           1 :   tor_cert_free(cert);
     739           1 : }
     740             : 
     741             : static void
     742           1 : test_desc_signature(void *arg)
     743             : {
     744           1 :   int ret;
     745           1 :   char *data = NULL, *desc = NULL;
     746           1 :   char sig_b64[ED25519_SIG_BASE64_LEN + 1];
     747           1 :   ed25519_keypair_t kp;
     748           1 :   ed25519_signature_t sig;
     749             : 
     750           1 :   (void) arg;
     751             : 
     752           1 :   ed25519_keypair_generate(&kp, 0);
     753             :   /* Setup a phoony descriptor but with a valid signature token that is the
     754             :    * signature is verifiable. */
     755           1 :   tor_asprintf(&data, "This is a signed descriptor\n");
     756           1 :   ret = ed25519_sign_prefixed(&sig, (const uint8_t *) data, strlen(data),
     757             :                               "Tor onion service descriptor sig v3", &kp);
     758           1 :   tt_int_op(ret, OP_EQ, 0);
     759           1 :   ed25519_signature_to_base64(sig_b64, &sig);
     760             :   /* Build the descriptor that should be valid. */
     761           1 :   tor_asprintf(&desc, "%ssignature %s\n", data, sig_b64);
     762           1 :   ret = desc_sig_is_valid(sig_b64, &kp.pubkey, desc, strlen(desc));
     763           1 :   tt_int_op(ret, OP_EQ, 1);
     764             :   /* Junk signature. */
     765           1 :   ret = desc_sig_is_valid("JUNK", &kp.pubkey, desc, strlen(desc));
     766           1 :   tt_int_op(ret, OP_EQ, 0);
     767             : 
     768           1 :  done:
     769           1 :   tor_free(desc);
     770           1 :   tor_free(data);
     771           1 : }
     772             : 
     773             : static void
     774           1 : test_build_authorized_client(void *arg)
     775             : {
     776           1 :   int ret;
     777           1 :   hs_desc_authorized_client_t *desc_client = NULL;
     778           1 :   uint8_t descriptor_cookie[HS_DESC_DESCRIPTOR_COOKIE_LEN];
     779           1 :   curve25519_secret_key_t auth_ephemeral_sk;
     780           1 :   curve25519_secret_key_t client_auth_sk;
     781           1 :   curve25519_public_key_t client_auth_pk;
     782           1 :   const char ephemeral_sk_b16[] =
     783             :     "d023b674d993a5c8446bd2ca97e9961149b3c0e88c7dc14e8777744dd3468d6a";
     784           1 :   const char descriptor_cookie_b16[] =
     785             :     "07d087f1d8c68393721f6e70316d3b29";
     786           1 :   const char client_pubkey_b16[] =
     787             :     "8c1298fa6050e372f8598f6deca32e27b0ad457741422c2629ebb132cf7fae37";
     788           1 :   hs_subcredential_t subcredential;
     789           1 :   char *mem_op_hex_tmp=NULL;
     790             : 
     791           1 :   (void) arg;
     792             : 
     793           1 :   ret = curve25519_secret_key_generate(&auth_ephemeral_sk, 0);
     794           1 :   tt_int_op(ret, OP_EQ, 0);
     795             : 
     796           1 :   ret = curve25519_secret_key_generate(&client_auth_sk, 0);
     797           1 :   tt_int_op(ret, OP_EQ, 0);
     798           1 :   curve25519_public_key_generate(&client_auth_pk, &client_auth_sk);
     799             : 
     800           1 :   memset(subcredential.subcred, 42, sizeof(subcredential));
     801             : 
     802           1 :   desc_client = tor_malloc_zero(sizeof(hs_desc_authorized_client_t));
     803             : 
     804           1 :   base16_decode((char *) &auth_ephemeral_sk,
     805             :                 sizeof(auth_ephemeral_sk),
     806             :                 ephemeral_sk_b16,
     807             :                 strlen(ephemeral_sk_b16));
     808             : 
     809           1 :   base16_decode((char *) descriptor_cookie,
     810             :                 sizeof(descriptor_cookie),
     811             :                 descriptor_cookie_b16,
     812             :                 strlen(descriptor_cookie_b16));
     813             : 
     814           1 :   base16_decode((char *) &client_auth_pk,
     815             :                 sizeof(client_auth_pk),
     816             :                 client_pubkey_b16,
     817             :                 strlen(client_pubkey_b16));
     818             : 
     819           1 :   testing_enable_prefilled_rng("\x01", 1);
     820             : 
     821           1 :   hs_desc_build_authorized_client(&subcredential,
     822             :                                   &client_auth_pk, &auth_ephemeral_sk,
     823             :                                   descriptor_cookie, desc_client);
     824             : 
     825           1 :   test_memeq_hex((char *) desc_client->client_id,
     826             :                  "EC19B7FF4D2DDA13");
     827           1 :   test_memeq_hex((char *) desc_client->iv,
     828             :                 "01010101010101010101010101010101");
     829           1 :   test_memeq_hex((char *) desc_client->encrypted_cookie,
     830             :                 "B21222BE13F385F355BD07B2381F9F29");
     831             : 
     832           1 :  done:
     833           1 :   tor_free(desc_client);
     834           1 :   tor_free(mem_op_hex_tmp);
     835           1 :   testing_disable_prefilled_rng();
     836           1 : }
     837             : 
     838             : struct testcase_t hs_descriptor[] = {
     839             :   /* Encoding tests. */
     840             :   { "cert_encoding", test_cert_encoding, TT_FORK,
     841             :     NULL, NULL },
     842             :   { "encode_descriptor", test_encode_descriptor, TT_FORK,
     843             :     NULL, NULL },
     844             :   { "descriptor_padding", test_descriptor_padding, TT_FORK,
     845             :     NULL, NULL },
     846             : 
     847             :   /* Decoding tests. */
     848             :   { "decode_descriptor", test_decode_descriptor, TT_FORK,
     849             :     NULL, NULL },
     850             :   { "encrypted_data_len", test_encrypted_data_len, TT_FORK,
     851             :     NULL, NULL },
     852             :   { "decode_invalid_intro_point", test_decode_invalid_intro_point, TT_FORK,
     853             :     NULL, NULL },
     854             :   { "decode_plaintext", test_decode_plaintext, TT_FORK,
     855             :     NULL, NULL },
     856             :   { "decode_bad_signature", test_decode_bad_signature, TT_FORK,
     857             :     NULL, NULL },
     858             : 
     859             :   /* Misc. */
     860             :   { "version", test_supported_version, TT_FORK,
     861             :     NULL, NULL },
     862             :   { "validate_cert", test_validate_cert, TT_FORK,
     863             :     NULL, NULL },
     864             :   { "desc_signature", test_desc_signature, TT_FORK,
     865             :     NULL, NULL },
     866             :   { "build_authorized_client", test_build_authorized_client, TT_FORK,
     867             :     NULL, NULL },
     868             : 
     869             :   END_OF_TESTCASES
     870             : };

Generated by: LCOV version 1.14