[tor-commits] [tor/master] Turn hs_subcredential_t into a proper struct.

nickm at torproject.org nickm at torproject.org
Mon Feb 24 12:48:35 UTC 2020


commit 4532c7ef6aa96d502412cbc61da91369bc3eaa44
Author: Nick Mathewson <nickm at torproject.org>
Date:   Thu Jan 16 18:27:25 2020 -0500

    Turn hs_subcredential_t into a proper struct.
---
 src/core/crypto/hs_ntor.c      |  8 ++++----
 src/core/crypto/hs_ntor.h      | 13 +++++++++++--
 src/feature/hs/hs_cell.c       |  6 +++---
 src/feature/hs/hs_cell.h       |  6 ++++--
 src/feature/hs/hs_circuit.c    |  6 +++---
 src/feature/hs/hs_circuit.h    |  5 +++--
 src/feature/hs/hs_client.c     | 12 ++++++------
 src/feature/hs/hs_common.c     |  7 ++++---
 src/feature/hs/hs_common.h     |  3 ++-
 src/feature/hs/hs_descriptor.c | 24 +++++++++++++-----------
 src/feature/hs/hs_descriptor.h |  7 ++++---
 src/feature/hs/hs_ob.c         | 12 +++++-------
 src/feature/hs/hs_ob.h         |  3 ++-
 src/feature/hs/hs_service.c    |  9 +++++----
 src/test/fuzz/fuzz_hsdescv3.c  |  7 +++----
 src/test/hs_test_helpers.c     |  6 +++---
 src/test/hs_test_helpers.h     |  7 +++----
 src/test/test_hs_cache.c       | 21 ++++++++++++---------
 src/test/test_hs_client.c      |  7 ++++---
 src/test/test_hs_descriptor.c  | 28 ++++++++++++++--------------
 src/test/test_hs_ntor.c        |  8 ++++----
 src/test/test_hs_ntor_cl.c     | 16 ++++++++--------
 src/test/test_hs_ob.c          | 11 +++++------
 23 files changed, 125 insertions(+), 107 deletions(-)

diff --git a/src/core/crypto/hs_ntor.c b/src/core/crypto/hs_ntor.c
index 2bd4c3244..0422e7279 100644
--- a/src/core/crypto/hs_ntor.c
+++ b/src/core/crypto/hs_ntor.c
@@ -170,7 +170,7 @@ get_rendezvous1_key_material(const uint8_t *rend_secret_hs_input,
  * necessary key material, and return 0. */
 static void
 get_introduce1_key_material(const uint8_t *secret_input,
-                        const uint8_t *subcredential,
+                        const hs_subcredential_t *subcredential,
                         hs_ntor_intro_cell_keys_t *hs_ntor_intro_cell_keys_out)
 {
   uint8_t keystream[CIPHER256_KEY_LEN + DIGEST256_LEN];
@@ -181,7 +181,7 @@ get_introduce1_key_material(const uint8_t *secret_input,
   /* Let's build info */
   ptr = info_blob;
   APPEND(ptr, M_HSEXPAND, strlen(M_HSEXPAND));
-  APPEND(ptr, subcredential, DIGEST256_LEN);
+  APPEND(ptr, subcredential->subcred, SUBCRED_LEN);
   tor_assert(ptr == info_blob + sizeof(info_blob));
 
   /* Let's build the input to the KDF */
@@ -317,7 +317,7 @@ hs_ntor_client_get_introduce1_keys(
                       const ed25519_public_key_t *intro_auth_pubkey,
                       const curve25519_public_key_t *intro_enc_pubkey,
                       const curve25519_keypair_t *client_ephemeral_enc_keypair,
-                      const uint8_t *subcredential,
+                      const hs_subcredential_t *subcredential,
                       hs_ntor_intro_cell_keys_t *hs_ntor_intro_cell_keys_out)
 {
   int bad = 0;
@@ -450,7 +450,7 @@ hs_ntor_service_get_introduce1_keys(
                     const ed25519_public_key_t *intro_auth_pubkey,
                     const curve25519_keypair_t *intro_enc_keypair,
                     const curve25519_public_key_t *client_ephemeral_enc_pubkey,
-                    const uint8_t *subcredential,
+                    const hs_subcredential_t *subcredential,
                     hs_ntor_intro_cell_keys_t *hs_ntor_intro_cell_keys_out)
 {
   int bad = 0;
diff --git a/src/core/crypto/hs_ntor.h b/src/core/crypto/hs_ntor.h
index 2bce5686c..b78bc4e80 100644
--- a/src/core/crypto/hs_ntor.h
+++ b/src/core/crypto/hs_ntor.h
@@ -35,11 +35,20 @@ typedef struct hs_ntor_rend_cell_keys_t {
   uint8_t ntor_key_seed[DIGEST256_LEN];
 } hs_ntor_rend_cell_keys_t;
 
+#define SUBCRED_LEN DIGEST256_LEN
+
+/**
+ * A 'subcredential' used to prove knowledge of a hidden service.
+ **/
+typedef struct hs_subcredential_t {
+  uint8_t subcred[SUBCRED_LEN];
+} hs_subcredential_t;
+
 int hs_ntor_client_get_introduce1_keys(
               const struct ed25519_public_key_t *intro_auth_pubkey,
               const struct curve25519_public_key_t *intro_enc_pubkey,
               const struct curve25519_keypair_t *client_ephemeral_enc_keypair,
-              const uint8_t *subcredential,
+              const hs_subcredential_t *subcredential,
               hs_ntor_intro_cell_keys_t *hs_ntor_intro_cell_keys_out);
 
 int hs_ntor_client_get_rendezvous1_keys(
@@ -53,7 +62,7 @@ int hs_ntor_service_get_introduce1_keys(
             const struct ed25519_public_key_t *intro_auth_pubkey,
             const struct curve25519_keypair_t *intro_enc_keypair,
             const struct curve25519_public_key_t *client_ephemeral_enc_pubkey,
-            const uint8_t *subcredential,
+            const hs_subcredential_t *subcredential,
             hs_ntor_intro_cell_keys_t *hs_ntor_intro_cell_keys_out);
 
 int hs_ntor_service_get_rendezvous1_keys(
diff --git a/src/feature/hs/hs_cell.c b/src/feature/hs/hs_cell.c
index aabc55859..d377e9134 100644
--- a/src/feature/hs/hs_cell.c
+++ b/src/feature/hs/hs_cell.c
@@ -75,7 +75,7 @@ compute_introduce_mac(const uint8_t *encoded_cell, size_t encoded_cell_len,
 static hs_ntor_intro_cell_keys_t *
 get_introduce2_key_material(const ed25519_public_key_t *auth_key,
                             const curve25519_keypair_t *enc_key,
-                            const uint8_t *subcredential,
+                            const hs_subcredential_t *subcredential,
                             const uint8_t *encrypted_section,
                             curve25519_public_key_t *client_pk)
 {
@@ -820,7 +820,7 @@ get_intro2_keys_as_ob(const hs_service_config_t *config,
                       const uint8_t *encrypted_section,
                       size_t encrypted_section_len)
 {
-  uint8_t *ob_subcreds = NULL;
+  hs_subcredential_t *ob_subcreds = NULL;
   size_t ob_num_subcreds;
   hs_ntor_intro_cell_keys_t *intro_keys = NULL;
 
@@ -835,7 +835,7 @@ get_intro2_keys_as_ob(const hs_service_config_t *config,
     /* Copy current data into a new INTRO2 cell data. We will then change the
      * subcredential in order to validate. */
     hs_cell_introduce2_data_t new_data = *data;
-    new_data.subcredential = &(ob_subcreds[idx * DIGEST256_LEN]);
+    new_data.subcredential = &ob_subcreds[idx];
     intro_keys = get_introduce2_keys_and_verify_mac(&new_data,
                                                     encrypted_section,
                                                     encrypted_section_len);
diff --git a/src/feature/hs/hs_cell.h b/src/feature/hs/hs_cell.h
index 80f37057d..58cc401cc 100644
--- a/src/feature/hs/hs_cell.h
+++ b/src/feature/hs/hs_cell.h
@@ -16,6 +16,8 @@
  * 3.2.2 of the specification). Below this value, the cell must be padded. */
 #define HS_CELL_INTRODUCE1_MIN_SIZE 246
 
+struct hs_subcredential_t;
+
 /** This data structure contains data that we need to build an INTRODUCE1 cell
  * used by the INTRODUCE1 build function. */
 typedef struct hs_cell_introduce1_data_t {
@@ -29,7 +31,7 @@ typedef struct hs_cell_introduce1_data_t {
   /** Introduction point encryption public key. */
   const curve25519_public_key_t *enc_pk;
   /** Subcredentials of the service. */
-  const uint8_t *subcredential;
+  const struct hs_subcredential_t *subcredential;
   /** Onion public key for the ntor handshake. */
   const curve25519_public_key_t *onion_pk;
   /** Rendezvous cookie. */
@@ -57,7 +59,7 @@ typedef struct hs_cell_introduce2_data_t {
   const curve25519_keypair_t *enc_kp;
   /** Subcredentials of the service. Pointer owned by the descriptor that owns
      the introduction point through which we received the INTRO2 cell. */
-  const uint8_t *subcredential;
+  const struct hs_subcredential_t *subcredential;
   /** Payload of the received encoded cell. */
   const uint8_t *payload;
   /** Size of the payload of the received encoded cell. */
diff --git a/src/feature/hs/hs_circuit.c b/src/feature/hs/hs_circuit.c
index 90805a98b..fb3694b2d 100644
--- a/src/feature/hs/hs_circuit.c
+++ b/src/feature/hs/hs_circuit.c
@@ -578,7 +578,7 @@ retry_service_rendezvous_point(const origin_circuit_t *circ)
 static int
 setup_introduce1_data(const hs_desc_intro_point_t *ip,
                       const node_t *rp_node,
-                      const uint8_t *subcredential,
+                      const hs_subcredential_t *subcredential,
                       hs_cell_introduce1_data_t *intro1_data)
 {
   int ret = -1;
@@ -966,7 +966,7 @@ int
 hs_circ_handle_introduce2(const hs_service_t *service,
                           const origin_circuit_t *circ,
                           hs_service_intro_point_t *ip,
-                          const uint8_t *subcredential,
+                          const hs_subcredential_t *subcredential,
                           const uint8_t *payload, size_t payload_len)
 {
   int ret = -1;
@@ -1092,7 +1092,7 @@ int
 hs_circ_send_introduce1(origin_circuit_t *intro_circ,
                         origin_circuit_t *rend_circ,
                         const hs_desc_intro_point_t *ip,
-                        const uint8_t *subcredential)
+                        const hs_subcredential_t *subcredential)
 {
   int ret = -1;
   ssize_t payload_len;
diff --git a/src/feature/hs/hs_circuit.h b/src/feature/hs/hs_circuit.h
index 92231369c..5c20e3818 100644
--- a/src/feature/hs/hs_circuit.h
+++ b/src/feature/hs/hs_circuit.h
@@ -46,15 +46,16 @@ int hs_circ_handle_intro_established(const hs_service_t *service,
                                      origin_circuit_t *circ,
                                      const uint8_t *payload,
                                      size_t payload_len);
+struct hs_subcredential_t;
 int hs_circ_handle_introduce2(const hs_service_t *service,
                               const origin_circuit_t *circ,
                               hs_service_intro_point_t *ip,
-                              const uint8_t *subcredential,
+                              const struct hs_subcredential_t *subcredential,
                               const uint8_t *payload, size_t payload_len);
 int hs_circ_send_introduce1(origin_circuit_t *intro_circ,
                             origin_circuit_t *rend_circ,
                             const hs_desc_intro_point_t *ip,
-                            const uint8_t *subcredential);
+                            const struct hs_subcredential_t *subcredential);
 int hs_circ_send_establish_rendezvous(origin_circuit_t *circ);
 
 /* e2e circuit API. */
diff --git a/src/feature/hs/hs_client.c b/src/feature/hs/hs_client.c
index bcb0495c6..601062190 100644
--- a/src/feature/hs/hs_client.c
+++ b/src/feature/hs/hs_client.c
@@ -641,7 +641,7 @@ send_introduce1(origin_circuit_t *intro_circ,
 
   /* Send the INTRODUCE1 cell. */
   if (hs_circ_send_introduce1(intro_circ, rend_circ, ip,
-                              desc->subcredential) < 0) {
+                              &desc->subcredential) < 0) {
     if (TO_CIRCUIT(intro_circ)->marked_for_close) {
       /* If the introduction circuit was closed, we were unable to send the
        * cell for some reasons. In any case, the intro circuit has to be
@@ -1817,7 +1817,7 @@ hs_client_decode_descriptor(const char *desc_str,
                             hs_descriptor_t **desc)
 {
   hs_desc_decode_status_t ret;
-  uint8_t subcredential[DIGEST256_LEN];
+  hs_subcredential_t subcredential;
   ed25519_public_key_t blinded_pubkey;
   hs_client_service_authorization_t *client_auth = NULL;
   curve25519_secret_key_t *client_auht_sk = NULL;
@@ -1837,13 +1837,14 @@ hs_client_decode_descriptor(const char *desc_str,
     uint64_t current_time_period = hs_get_time_period_num(0);
     hs_build_blinded_pubkey(service_identity_pk, NULL, 0, current_time_period,
                             &blinded_pubkey);
-    hs_get_subcredential(service_identity_pk, &blinded_pubkey, subcredential);
+    hs_get_subcredential(service_identity_pk, &blinded_pubkey, &
+                         subcredential);
   }
 
   /* Parse descriptor */
-  ret = hs_desc_decode_descriptor(desc_str, subcredential,
+  ret = hs_desc_decode_descriptor(desc_str, &subcredential,
                                   client_auht_sk, desc);
-  memwipe(subcredential, 0, sizeof(subcredential));
+  memwipe(&subcredential, 0, sizeof(subcredential));
   if (ret != HS_DESC_DECODE_OK) {
     goto err;
   }
@@ -2456,4 +2457,3 @@ set_hs_client_auths_map(digest256map_t *map)
 }
 
 #endif /* defined(TOR_UNIT_TESTS) */
-
diff --git a/src/feature/hs/hs_common.c b/src/feature/hs/hs_common.c
index 47594b582..b2b52c480 100644
--- a/src/feature/hs/hs_common.c
+++ b/src/feature/hs/hs_common.c
@@ -808,12 +808,12 @@ hs_parse_address_impl(const char *address, ed25519_public_key_t *key_out,
 }
 
 /** Using the given identity public key and a blinded public key, compute the
- * subcredential and put it in subcred_out (must be of size DIGEST256_LEN).
+ * subcredential and put it in subcred_out.
  * This can't fail. */
 void
 hs_get_subcredential(const ed25519_public_key_t *identity_pk,
                      const ed25519_public_key_t *blinded_pk,
-                     uint8_t *subcred_out)
+                     hs_subcredential_t *subcred_out)
 {
   uint8_t credential[DIGEST256_LEN];
   crypto_digest_t *digest;
@@ -841,7 +841,8 @@ hs_get_subcredential(const ed25519_public_key_t *identity_pk,
                           sizeof(credential));
   crypto_digest_add_bytes(digest, (const char *) blinded_pk->pubkey,
                           ED25519_PUBKEY_LEN);
-  crypto_digest_get_digest(digest, (char *) subcred_out, DIGEST256_LEN);
+  crypto_digest_get_digest(digest, (char *) subcred_out->subcred,
+                           SUBCRED_LEN);
   crypto_digest_free(digest);
 
   memwipe(credential, 0, sizeof(credential));
diff --git a/src/feature/hs/hs_common.h b/src/feature/hs/hs_common.h
index 2bcf0f67c..997b7298a 100644
--- a/src/feature/hs/hs_common.h
+++ b/src/feature/hs/hs_common.h
@@ -214,9 +214,10 @@ const uint8_t *rend_data_get_pk_digest(const rend_data_t *rend_data,
 
 routerstatus_t *pick_hsdir(const char *desc_id, const char *desc_id_base32);
 
+struct hs_subcredential_t;
 void hs_get_subcredential(const struct ed25519_public_key_t *identity_pk,
                           const struct ed25519_public_key_t *blinded_pk,
-                          uint8_t *subcred_out);
+                          struct hs_subcredential_t *subcred_out);
 
 uint64_t hs_get_previous_time_period_num(time_t now);
 uint64_t hs_get_time_period_num(time_t now);
diff --git a/src/feature/hs/hs_descriptor.c b/src/feature/hs/hs_descriptor.c
index 65d6c7a58..7f28e1c34 100644
--- a/src/feature/hs/hs_descriptor.c
+++ b/src/feature/hs/hs_descriptor.c
@@ -211,7 +211,7 @@ build_secret_input(const hs_descriptor_t *desc,
   memcpy(secret_input, secret_data, secret_data_len);
   offset += secret_data_len;
   /* Copy subcredential. */
-  memcpy(secret_input + offset, desc->subcredential, DIGEST256_LEN);
+  memcpy(secret_input + offset, desc->subcredential.subcred, DIGEST256_LEN);
   offset += DIGEST256_LEN;
   /* Copy revision counter value. */
   set_uint64(secret_input + offset,
@@ -1018,9 +1018,11 @@ desc_encode_v3(const hs_descriptor_t *desc,
   tor_assert(encoded_out);
   tor_assert(desc->plaintext_data.version == 3);
 
+  /* This is impossible; this is a member of desc.
   if (BUG(desc->subcredential == NULL)) {
     goto err;
   }
+  */
 
   /* Build the non-encrypted values. */
   {
@@ -1366,8 +1368,7 @@ encrypted_data_length_is_valid(size_t len)
  * and return the buffer's length. The caller should wipe and free its content
  * once done with it. This function can't fail. */
 static size_t
-build_descriptor_cookie_keys(const uint8_t *subcredential,
-                             size_t subcredential_len,
+build_descriptor_cookie_keys(const hs_subcredential_t *subcredential,
                              const curve25519_secret_key_t *sk,
                              const curve25519_public_key_t *pk,
                              uint8_t **keys_out)
@@ -1389,7 +1390,7 @@ build_descriptor_cookie_keys(const uint8_t *subcredential,
 
   /* Calculate KEYS = KDF(subcredential | SECRET_SEED, 40) */
   xof = crypto_xof_new();
-  crypto_xof_add_bytes(xof, subcredential, subcredential_len);
+  crypto_xof_add_bytes(xof, subcredential->subcred, SUBCRED_LEN);
   crypto_xof_add_bytes(xof, secret_seed, sizeof(secret_seed));
   crypto_xof_squeeze_bytes(xof, keystream, keystream_len);
   crypto_xof_free(xof);
@@ -1426,11 +1427,12 @@ decrypt_descriptor_cookie(const hs_descriptor_t *desc,
         sizeof(desc->superencrypted_data.auth_ephemeral_pubkey)));
   tor_assert(!fast_mem_is_zero((char *) client_auth_sk,
                               sizeof(*client_auth_sk)));
-  tor_assert(!fast_mem_is_zero((char *) desc->subcredential, DIGEST256_LEN));
+  tor_assert(!fast_mem_is_zero((char *) desc->subcredential.subcred,
+                               DIGEST256_LEN));
 
   /* Get the KEYS component to derive the CLIENT-ID and COOKIE-KEY. */
   keystream_length =
-    build_descriptor_cookie_keys(desc->subcredential, DIGEST256_LEN,
+    build_descriptor_cookie_keys(&desc->subcredential,
                              client_auth_sk,
                              &desc->superencrypted_data.auth_ephemeral_pubkey,
                              &keystream);
@@ -2558,7 +2560,7 @@ hs_desc_decode_plaintext(const char *encoded,
  * set to NULL. */
 hs_desc_decode_status_t
 hs_desc_decode_descriptor(const char *encoded,
-                          const uint8_t *subcredential,
+                          const hs_subcredential_t *subcredential,
                           const curve25519_secret_key_t *client_auth_sk,
                           hs_descriptor_t **desc_out)
 {
@@ -2576,7 +2578,7 @@ hs_desc_decode_descriptor(const char *encoded,
     goto err;
   }
 
-  memcpy(desc->subcredential, subcredential, sizeof(desc->subcredential));
+  memcpy(&desc->subcredential, subcredential, sizeof(desc->subcredential));
 
   ret = hs_desc_decode_plaintext(encoded, &desc->plaintext_data);
   if (ret != HS_DESC_DECODE_OK) {
@@ -2666,7 +2668,7 @@ hs_desc_encode_descriptor,(const hs_descriptor_t *desc,
    * symmetric only if the client auth is disabled. That is, the descriptor
    * cookie will be NULL. */
   if (!descriptor_cookie) {
-    ret = hs_desc_decode_descriptor(*encoded_out, desc->subcredential,
+    ret = hs_desc_decode_descriptor(*encoded_out, &desc->subcredential,
                                     NULL, NULL);
     if (BUG(ret != HS_DESC_DECODE_OK)) {
       ret = -1;
@@ -2870,7 +2872,7 @@ hs_desc_build_fake_authorized_client(void)
  * key, and descriptor cookie, build the auth client so we can then encode the
  * descriptor for publication. client_out must be already allocated. */
 void
-hs_desc_build_authorized_client(const uint8_t *subcredential,
+hs_desc_build_authorized_client(const hs_subcredential_t *subcredential,
                                 const curve25519_public_key_t *client_auth_pk,
                                 const curve25519_secret_key_t *
                                 auth_ephemeral_sk,
@@ -2898,7 +2900,7 @@ hs_desc_build_authorized_client(const uint8_t *subcredential,
 
   /* Get the KEYS part so we can derive the CLIENT-ID and COOKIE-KEY. */
   keystream_length =
-    build_descriptor_cookie_keys(subcredential, DIGEST256_LEN,
+    build_descriptor_cookie_keys(subcredential,
                                  auth_ephemeral_sk, client_auth_pk,
                                  &keystream);
   tor_assert(keystream_length > 0);
diff --git a/src/feature/hs/hs_descriptor.h b/src/feature/hs/hs_descriptor.h
index 639dd31c8..08daa904b 100644
--- a/src/feature/hs/hs_descriptor.h
+++ b/src/feature/hs/hs_descriptor.h
@@ -14,6 +14,7 @@
 #include "core/or/or.h"
 #include "trunnel/ed25519_cert.h" /* needed for trunnel */
 #include "feature/nodelist/torcert.h"
+#include "core/crypto/hs_ntor.h" /* for hs_subcredential_t */
 
 /* Trunnel */
 struct link_specifier_t;
@@ -238,7 +239,7 @@ typedef struct hs_descriptor_t {
 
   /** Subcredentials of a service, used by the client and service to decrypt
    * the encrypted data. */
-  uint8_t subcredential[DIGEST256_LEN];
+  hs_subcredential_t subcredential;
 } hs_descriptor_t;
 
 /** Return true iff the given descriptor format version is supported. */
@@ -277,7 +278,7 @@ MOCK_DECL(int,
                                      char **encoded_out));
 
 int hs_desc_decode_descriptor(const char *encoded,
-                              const uint8_t *subcredential,
+                              const hs_subcredential_t *subcredential,
                               const curve25519_secret_key_t *client_auth_sk,
                               hs_descriptor_t **desc_out);
 int hs_desc_decode_plaintext(const char *encoded,
@@ -302,7 +303,7 @@ void hs_desc_authorized_client_free_(hs_desc_authorized_client_t *client);
 
 hs_desc_authorized_client_t *hs_desc_build_fake_authorized_client(void);
 
-void hs_desc_build_authorized_client(const uint8_t *subcredential,
+void hs_desc_build_authorized_client(const hs_subcredential_t *subcredential,
                                      const curve25519_public_key_t *
                                      client_auth_pk,
                                      const curve25519_secret_key_t *
diff --git a/src/feature/hs/hs_ob.c b/src/feature/hs/hs_ob.c
index 62db3bd43..ee54595f2 100644
--- a/src/feature/hs/hs_ob.c
+++ b/src/feature/hs/hs_ob.c
@@ -178,7 +178,7 @@ ob_option_parse(hs_service_config_t *config, const ob_options_t *opts)
  * least DIGEST256_LEN in size. */
 static void
 build_subcredential(const ed25519_public_key_t *pkey, uint64_t tp,
-                    uint8_t *subcredential)
+                    hs_subcredential_t *subcredential)
 {
   ed25519_public_key_t blinded_pubkey;
 
@@ -275,13 +275,12 @@ hs_ob_parse_config_file(hs_service_config_t *config)
  * Otherwise, this can't fail. */
 size_t
 hs_ob_get_subcredentials(const hs_service_config_t *config,
-                         uint8_t **subcredentials)
+                         hs_subcredential_t **subcredentials)
 {
   unsigned int num_pkeys, idx = 0;
-  uint8_t *subcreds = NULL;
+  hs_subcredential_t *subcreds = NULL;
   const int steps[3] = {0, -1, 1};
   const unsigned int num_steps = ARRAY_LENGTH(steps);
-  const size_t subcred_len = DIGEST256_LEN;
   const uint64_t tp = hs_get_time_period_num(0);
 
   tor_assert(config);
@@ -319,14 +318,13 @@ hs_ob_get_subcredentials(const hs_service_config_t *config,
    * number of time period we need to compute and finally multiplied by the
    * total number of keys we are about to process. In other words, for each
    * key, we allocate 3 subcredential slots. */
-  subcreds = tor_malloc_zero(subcred_len * num_steps * num_pkeys);
+  subcreds = tor_calloc(num_steps * num_pkeys, sizeof(hs_subcredential_t));
 
   /* For each time period step. */
   for (unsigned int i = 0; i < num_steps; i++) {
     SMARTLIST_FOREACH_BEGIN(config->ob_master_pubkeys,
                             const ed25519_public_key_t *, pkey) {
-      build_subcredential(pkey, tp + steps[i],
-                          &(subcreds[idx * subcred_len]));
+      build_subcredential(pkey, tp + steps[i], &subcreds[idx]);
       idx++;
     } SMARTLIST_FOREACH_END(pkey);
   }
diff --git a/src/feature/hs/hs_ob.h b/src/feature/hs/hs_ob.h
index fea6a737d..37e94808c 100644
--- a/src/feature/hs/hs_ob.h
+++ b/src/feature/hs/hs_ob.h
@@ -15,8 +15,9 @@ bool hs_ob_service_is_instance(const hs_service_t *service);
 
 int hs_ob_parse_config_file(hs_service_config_t *config);
 
+struct hs_subcredential_t;
 size_t hs_ob_get_subcredentials(const hs_service_config_t *config,
-                                uint8_t **subcredentials);
+                                struct hs_subcredential_t **subcredentials);
 
 #ifdef HS_OB_PRIVATE
 
diff --git a/src/feature/hs/hs_service.c b/src/feature/hs/hs_service.c
index d0d9d6579..87b9625f5 100644
--- a/src/feature/hs/hs_service.c
+++ b/src/feature/hs/hs_service.c
@@ -1769,7 +1769,8 @@ build_service_desc_superencrypted(const hs_service_t *service,
          sizeof(curve25519_public_key_t));
 
   /* Test that subcred is not zero because we might use it below */
-  if (BUG(fast_mem_is_zero((char*)desc->desc->subcredential, DIGEST256_LEN))) {
+  if (BUG(fast_mem_is_zero((char*)desc->desc->subcredential.subcred,
+                           DIGEST256_LEN))) {
     return -1;
   }
 
@@ -1786,7 +1787,7 @@ build_service_desc_superencrypted(const hs_service_t *service,
 
       /* Prepare the client for descriptor and then add to the list in the
        * superencrypted part of the descriptor */
-      hs_desc_build_authorized_client(desc->desc->subcredential,
+      hs_desc_build_authorized_client(&desc->desc->subcredential,
                                       &client->client_pk,
                                       &desc->auth_ephemeral_kp.seckey,
                                       desc->descriptor_cookie, desc_client);
@@ -1842,7 +1843,7 @@ build_service_desc_plaintext(const hs_service_t *service,
 
   /* Set the subcredential. */
   hs_get_subcredential(&service->keys.identity_pk, &desc->blinded_kp.pubkey,
-                       desc->desc->subcredential);
+                       &desc->desc->subcredential);
 
   plaintext = &desc->desc->plaintext_data;
 
@@ -3374,7 +3375,7 @@ service_handle_introduce2(origin_circuit_t *circ, const uint8_t *payload,
 
   /* The following will parse, decode and launch the rendezvous point circuit.
    * Both current and legacy cells are handled. */
-  if (hs_circ_handle_introduce2(service, circ, ip, desc->desc->subcredential,
+  if (hs_circ_handle_introduce2(service, circ, ip, &desc->desc->subcredential,
                                 payload, payload_len) < 0) {
     goto err;
   }
diff --git a/src/test/fuzz/fuzz_hsdescv3.c b/src/test/fuzz/fuzz_hsdescv3.c
index 395524138..8d7eab1a8 100644
--- a/src/test/fuzz/fuzz_hsdescv3.c
+++ b/src/test/fuzz/fuzz_hsdescv3.c
@@ -85,12 +85,12 @@ int
 fuzz_main(const uint8_t *data, size_t sz)
 {
   hs_descriptor_t *desc = NULL;
-  uint8_t subcredential[DIGEST256_LEN];
+  hs_subcredential_t subcredential;
 
   char *fuzzing_data = tor_memdup_nulterm(data, sz);
-  memset(subcredential, 'A', sizeof(subcredential));
+  memset(&subcredential, 'A', sizeof(subcredential));
 
-  hs_desc_decode_descriptor(fuzzing_data, subcredential, NULL, &desc);
+  hs_desc_decode_descriptor(fuzzing_data, &subcredential, NULL, &desc);
   if (desc) {
     log_debug(LD_GENERAL, "Decoding okay");
     hs_descriptor_free(desc);
@@ -101,4 +101,3 @@ fuzz_main(const uint8_t *data, size_t sz)
   tor_free(fuzzing_data);
   return 0;
 }
-
diff --git a/src/test/hs_test_helpers.c b/src/test/hs_test_helpers.c
index e8b99aaac..eb4af1c9f 100644
--- a/src/test/hs_test_helpers.c
+++ b/src/test/hs_test_helpers.c
@@ -140,7 +140,7 @@ hs_helper_build_hs_desc_impl(unsigned int no_ip,
   desc->plaintext_data.lifetime_sec = 3 * 60 * 60;
 
   hs_get_subcredential(&signing_kp->pubkey, &blinded_kp.pubkey,
-                    desc->subcredential);
+                    &desc->subcredential);
 
   /* Setup superencrypted data section. */
   ret = curve25519_keypair_generate(&auth_ephemeral_kp, 0);
@@ -186,7 +186,7 @@ hs_helper_build_hs_desc_impl(unsigned int no_ip,
  *  an HS. Used to decrypt descriptors in unittests. */
 void
 hs_helper_get_subcred_from_identity_keypair(ed25519_keypair_t *signing_kp,
-                                            uint8_t *subcred_out)
+                                            hs_subcredential_t *subcred_out)
 {
   ed25519_keypair_t blinded_kp;
   uint64_t current_time_period = hs_get_time_period_num(approx_time());
@@ -233,7 +233,7 @@ hs_helper_build_hs_desc_with_client_auth(
   memcpy(&desc->superencrypted_data.auth_ephemeral_pubkey,
          &auth_ephemeral_kp.pubkey, sizeof(curve25519_public_key_t));
 
-  hs_desc_build_authorized_client(desc->subcredential, client_pk,
+  hs_desc_build_authorized_client(&desc->subcredential, client_pk,
                                   &auth_ephemeral_kp.seckey,
                                   descriptor_cookie, desc_client);
   smartlist_add(desc->superencrypted_data.clients, desc_client);
diff --git a/src/test/hs_test_helpers.h b/src/test/hs_test_helpers.h
index a01fd45d6..cad453282 100644
--- a/src/test/hs_test_helpers.h
+++ b/src/test/hs_test_helpers.h
@@ -21,12 +21,11 @@ hs_descriptor_t *hs_helper_build_hs_desc_with_client_auth(
                                  const ed25519_keypair_t *signing_kp);
 void hs_helper_desc_equal(const hs_descriptor_t *desc1,
                           const hs_descriptor_t *desc2);
-void
-hs_helper_get_subcred_from_identity_keypair(ed25519_keypair_t *signing_kp,
-                                            uint8_t *subcred_out);
+struct hs_subcredential_t;
+void hs_helper_get_subcred_from_identity_keypair(ed25519_keypair_t *signing_kp,
+                                      struct hs_subcredential_t *subcred_out);
 
 void hs_helper_add_client_auth(const ed25519_public_key_t *service_pk,
                                const curve25519_secret_key_t *client_sk);
 
 #endif /* !defined(TOR_HS_TEST_HELPERS_H) */
-
diff --git a/src/test/test_hs_cache.c b/src/test/test_hs_cache.c
index 9e0094d25..c1bff6eb7 100644
--- a/src/test/test_hs_cache.c
+++ b/src/test/test_hs_cache.c
@@ -370,7 +370,7 @@ test_hsdir_revision_counter_check(void *arg)
   hs_descriptor_t *published_desc = NULL;
   char *published_desc_str = NULL;
 
-  uint8_t subcredential[DIGEST256_LEN];
+  hs_subcredential_t subcredential;
   char *received_desc_str = NULL;
   hs_descriptor_t *received_desc = NULL;
 
@@ -407,11 +407,11 @@ test_hsdir_revision_counter_check(void *arg)
     const ed25519_public_key_t *blinded_key;
 
     blinded_key = &published_desc->plaintext_data.blinded_pubkey;
-    hs_get_subcredential(&signing_kp.pubkey, blinded_key, subcredential);
+    hs_get_subcredential(&signing_kp.pubkey, blinded_key, &subcredential);
     received_desc_str = helper_fetch_desc_from_hsdir(blinded_key);
 
     retval = hs_desc_decode_descriptor(received_desc_str,
-                                       subcredential, NULL, &received_desc);
+                                       &subcredential, NULL, &received_desc);
     tt_int_op(retval, OP_EQ, HS_DESC_DECODE_OK);
     tt_assert(received_desc);
 
@@ -444,7 +444,7 @@ test_hsdir_revision_counter_check(void *arg)
     received_desc_str = helper_fetch_desc_from_hsdir(blinded_key);
 
     retval = hs_desc_decode_descriptor(received_desc_str,
-                                       subcredential, NULL, &received_desc);
+                                       &subcredential, NULL, &received_desc);
     tt_int_op(retval, OP_EQ, HS_DESC_DECODE_OK);
     tt_assert(received_desc);
 
@@ -476,7 +476,7 @@ test_client_cache(void *arg)
   ed25519_keypair_t signing_kp;
   hs_descriptor_t *published_desc = NULL;
   char *published_desc_str = NULL;
-  uint8_t wanted_subcredential[DIGEST256_LEN];
+  hs_subcredential_t wanted_subcredential;
   response_handler_args_t *args = NULL;
   dir_connection_t *conn = NULL;
 
@@ -505,8 +505,10 @@ test_client_cache(void *arg)
     retval = hs_desc_encode_descriptor(published_desc, &signing_kp,
                                        NULL, &published_desc_str);
     tt_int_op(retval, OP_EQ, 0);
-    memcpy(wanted_subcredential, published_desc->subcredential, DIGEST256_LEN);
-    tt_assert(!fast_mem_is_zero((char*)wanted_subcredential, DIGEST256_LEN));
+    memcpy(&wanted_subcredential, &published_desc->subcredential,
+           sizeof(hs_subcredential_t));
+    tt_assert(!fast_mem_is_zero((char*)wanted_subcredential.subcred,
+                                DIGEST256_LEN));
   }
 
   /* Test handle_response_fetch_hsdesc_v3() */
@@ -540,8 +542,9 @@ test_client_cache(void *arg)
     const hs_descriptor_t *cached_desc = NULL;
     cached_desc = hs_cache_lookup_as_client(&signing_kp.pubkey);
     tt_assert(cached_desc);
-    tt_mem_op(cached_desc->subcredential, OP_EQ, wanted_subcredential,
-              DIGEST256_LEN);
+    tt_mem_op(cached_desc->subcredential.subcred,
+              OP_EQ, wanted_subcredential.subcred,
+              SUBCRED_LEN);
   }
 
   /* Progress time to next TP and check that desc was cleaned */
diff --git a/src/test/test_hs_client.c b/src/test/test_hs_client.c
index 9f09cc3ec..88910e8ea 100644
--- a/src/test/test_hs_client.c
+++ b/src/test/test_hs_client.c
@@ -416,9 +416,10 @@ test_client_pick_intro(void *arg)
     const hs_descriptor_t *fetched_desc =
       hs_cache_lookup_as_client(&service_kp.pubkey);
     tt_assert(fetched_desc);
-    tt_mem_op(fetched_desc->subcredential, OP_EQ, desc->subcredential,
-              DIGEST256_LEN);
-    tt_assert(!fast_mem_is_zero((char*)fetched_desc->subcredential,
+    tt_mem_op(fetched_desc->subcredential.subcred,
+              OP_EQ, desc->subcredential.subcred,
+              SUBCRED_LEN);
+    tt_assert(!fast_mem_is_zero((char*)fetched_desc->subcredential.subcred,
                                DIGEST256_LEN));
     tor_free(encoded);
   }
diff --git a/src/test/test_hs_descriptor.c b/src/test/test_hs_descriptor.c
index 43ac5490a..61ccd3f91 100644
--- a/src/test/test_hs_descriptor.c
+++ b/src/test/test_hs_descriptor.c
@@ -221,7 +221,7 @@ test_decode_descriptor(void *arg)
   hs_descriptor_t *desc = NULL;
   hs_descriptor_t *decoded = NULL;
   hs_descriptor_t *desc_no_ip = NULL;
-  uint8_t subcredential[DIGEST256_LEN];
+  hs_subcredential_t subcredential;
 
   (void) arg;
 
@@ -230,10 +230,10 @@ test_decode_descriptor(void *arg)
   desc = hs_helper_build_hs_desc_with_ip(&signing_kp);
 
   hs_helper_get_subcred_from_identity_keypair(&signing_kp,
-                                              subcredential);
+                                              &subcredential);
 
   /* Give some bad stuff to the decoding function. */
-  ret = hs_desc_decode_descriptor("hladfjlkjadf", subcredential,
+  ret = hs_desc_decode_descriptor("hladfjlkjadf", &subcredential,
                                   NULL, &decoded);
   tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
 
@@ -241,7 +241,7 @@ test_decode_descriptor(void *arg)
   tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
   tt_assert(encoded);
 
-  ret = hs_desc_decode_descriptor(encoded, subcredential, NULL, &decoded);
+  ret = hs_desc_decode_descriptor(encoded, &subcredential, NULL, &decoded);
   tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
   tt_assert(decoded);
 
@@ -253,7 +253,7 @@ test_decode_descriptor(void *arg)
     ret = ed25519_keypair_generate(&signing_kp_no_ip, 0);
     tt_int_op(ret, OP_EQ, 0);
     hs_helper_get_subcred_from_identity_keypair(&signing_kp_no_ip,
-                                                subcredential);
+                                                &subcredential);
     desc_no_ip = hs_helper_build_hs_desc_no_ip(&signing_kp_no_ip);
     tt_assert(desc_no_ip);
     tor_free(encoded);
@@ -262,7 +262,7 @@ test_decode_descriptor(void *arg)
     tt_int_op(ret, OP_EQ, 0);
     tt_assert(encoded);
     hs_descriptor_free(decoded);
-    ret = hs_desc_decode_descriptor(encoded, subcredential, NULL, &decoded);
+    ret = hs_desc_decode_descriptor(encoded, &subcredential, NULL, &decoded);
     tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
     tt_assert(decoded);
   }
@@ -286,14 +286,14 @@ test_decode_descriptor(void *arg)
            &auth_ephemeral_kp.pubkey, CURVE25519_PUBKEY_LEN);
 
     hs_helper_get_subcred_from_identity_keypair(&signing_kp,
-                                                subcredential);
+                                                &subcredential);
 
     /* Build and add the auth client to the descriptor. */
     clients = desc->superencrypted_data.clients;
     if (!clients) {
       clients = smartlist_new();
     }
-    hs_desc_build_authorized_client(subcredential,
+    hs_desc_build_authorized_client(&subcredential,
                                     &client_kp.pubkey,
                                     &auth_ephemeral_kp.seckey,
                                     descriptor_cookie, client);
@@ -315,21 +315,21 @@ test_decode_descriptor(void *arg)
 
     /* If we do not have the client secret key, the decoding must fail. */
     hs_descriptor_free(decoded);
-    ret = hs_desc_decode_descriptor(encoded, subcredential,
+    ret = hs_desc_decode_descriptor(encoded, &subcredential,
                                     NULL, &decoded);
     tt_int_op(ret, OP_EQ, HS_DESC_DECODE_NEED_CLIENT_AUTH);
     tt_assert(!decoded);
 
     /* If we have an invalid client secret key, the decoding must fail. */
     hs_descriptor_free(decoded);
-    ret = hs_desc_decode_descriptor(encoded, subcredential,
+    ret = hs_desc_decode_descriptor(encoded, &subcredential,
                                     &invalid_client_kp.seckey, &decoded);
     tt_int_op(ret, OP_EQ, HS_DESC_DECODE_BAD_CLIENT_AUTH);
     tt_assert(!decoded);
 
     /* If we have the client secret key, the decoding must succeed and the
      * decoded descriptor must be correct. */
-    ret = hs_desc_decode_descriptor(encoded, subcredential,
+    ret = hs_desc_decode_descriptor(encoded, &subcredential,
                                     &client_kp.seckey, &decoded);
     tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
     tt_assert(decoded);
@@ -762,7 +762,7 @@ test_build_authorized_client(void *arg)
     "07d087f1d8c68393721f6e70316d3b29";
   const char client_pubkey_b16[] =
     "8c1298fa6050e372f8598f6deca32e27b0ad457741422c2629ebb132cf7fae37";
-  uint8_t subcredential[DIGEST256_LEN];
+  hs_subcredential_t subcredential;
   char *mem_op_hex_tmp=NULL;
 
   (void) arg;
@@ -774,7 +774,7 @@ test_build_authorized_client(void *arg)
   tt_int_op(ret, OP_EQ, 0);
   curve25519_public_key_generate(&client_auth_pk, &client_auth_sk);
 
-  memset(subcredential, 42, sizeof(subcredential));
+  memset(subcredential.subcred, 42, sizeof(subcredential));
 
   desc_client = tor_malloc_zero(sizeof(hs_desc_authorized_client_t));
 
@@ -795,7 +795,7 @@ test_build_authorized_client(void *arg)
 
   testing_enable_prefilled_rng("\x01", 1);
 
-  hs_desc_build_authorized_client(subcredential,
+  hs_desc_build_authorized_client(&subcredential,
                                   &client_auth_pk, &auth_ephemeral_sk,
                                   descriptor_cookie, desc_client);
 
diff --git a/src/test/test_hs_ntor.c b/src/test/test_hs_ntor.c
index 4f98bc85d..7867740a1 100644
--- a/src/test/test_hs_ntor.c
+++ b/src/test/test_hs_ntor.c
@@ -23,7 +23,7 @@ test_hs_ntor(void *arg)
 {
   int retval;
 
-  uint8_t subcredential[DIGEST256_LEN];
+  hs_subcredential_t subcredential;
 
   ed25519_keypair_t service_intro_auth_keypair;
   curve25519_keypair_t service_intro_enc_keypair;
@@ -42,7 +42,7 @@ test_hs_ntor(void *arg)
   /* Generate fake data for this unittest */
   {
     /* Generate fake subcredential */
-    memset(subcredential, 'Z', DIGEST256_LEN);
+    memset(subcredential.subcred, 'Z', DIGEST256_LEN);
 
     /* service */
     curve25519_keypair_generate(&service_intro_enc_keypair, 0);
@@ -57,7 +57,7 @@ test_hs_ntor(void *arg)
     hs_ntor_client_get_introduce1_keys(&service_intro_auth_keypair.pubkey,
                                        &service_intro_enc_keypair.pubkey,
                                        &client_ephemeral_enc_keypair,
-                                       subcredential,
+                                       &subcredential,
                                        &client_hs_ntor_intro_cell_keys);
   tt_int_op(retval, OP_EQ, 0);
 
@@ -66,7 +66,7 @@ test_hs_ntor(void *arg)
     hs_ntor_service_get_introduce1_keys(&service_intro_auth_keypair.pubkey,
                                         &service_intro_enc_keypair,
                                         &client_ephemeral_enc_keypair.pubkey,
-                                        subcredential,
+                                        &subcredential,
                                         &service_hs_ntor_intro_cell_keys);
   tt_int_op(retval, OP_EQ, 0);
 
diff --git a/src/test/test_hs_ntor_cl.c b/src/test/test_hs_ntor_cl.c
index a7cebc6af..3acd7ef0b 100644
--- a/src/test/test_hs_ntor_cl.c
+++ b/src/test/test_hs_ntor_cl.c
@@ -53,7 +53,7 @@ client1(int argc, char **argv)
   curve25519_public_key_t intro_enc_pubkey;
   ed25519_public_key_t intro_auth_pubkey;
   curve25519_keypair_t client_ephemeral_enc_keypair;
-  uint8_t subcredential[DIGEST256_LEN];
+  hs_subcredential_t subcredential;
 
   /* Output */
   hs_ntor_intro_cell_keys_t hs_ntor_intro_cell_keys;
@@ -65,7 +65,7 @@ client1(int argc, char **argv)
   BASE16(3, intro_enc_pubkey.public_key, CURVE25519_PUBKEY_LEN);
   BASE16(4, client_ephemeral_enc_keypair.seckey.secret_key,
          CURVE25519_SECKEY_LEN);
-  BASE16(5, subcredential, DIGEST256_LEN);
+  BASE16(5, subcredential.subcred, DIGEST256_LEN);
 
   /* Generate keypair */
   curve25519_public_key_generate(&client_ephemeral_enc_keypair.pubkey,
@@ -74,7 +74,7 @@ client1(int argc, char **argv)
   retval = hs_ntor_client_get_introduce1_keys(&intro_auth_pubkey,
                                               &intro_enc_pubkey,
                                               &client_ephemeral_enc_keypair,
-                                              subcredential,
+                                              &subcredential,
                                               &hs_ntor_intro_cell_keys);
   if (retval < 0) {
     goto done;
@@ -106,7 +106,7 @@ server1(int argc, char **argv)
   curve25519_keypair_t intro_enc_keypair;
   ed25519_public_key_t intro_auth_pubkey;
   curve25519_public_key_t client_ephemeral_enc_pubkey;
-  uint8_t subcredential[DIGEST256_LEN];
+  hs_subcredential_t subcredential;
 
   /* Output */
   hs_ntor_intro_cell_keys_t hs_ntor_intro_cell_keys;
@@ -119,7 +119,7 @@ server1(int argc, char **argv)
   BASE16(2, intro_auth_pubkey.pubkey, ED25519_PUBKEY_LEN);
   BASE16(3, intro_enc_keypair.seckey.secret_key, CURVE25519_SECKEY_LEN);
   BASE16(4, client_ephemeral_enc_pubkey.public_key, CURVE25519_PUBKEY_LEN);
-  BASE16(5, subcredential, DIGEST256_LEN);
+  BASE16(5, subcredential.subcred, DIGEST256_LEN);
 
   /* Generate keypair */
   curve25519_public_key_generate(&intro_enc_keypair.pubkey,
@@ -130,7 +130,7 @@ server1(int argc, char **argv)
   retval = hs_ntor_service_get_introduce1_keys(&intro_auth_pubkey,
                                                &intro_enc_keypair,
                                                &client_ephemeral_enc_pubkey,
-                                               subcredential,
+                                               &subcredential,
                                                &hs_ntor_intro_cell_keys);
   if (retval < 0) {
     goto done;
@@ -188,7 +188,7 @@ client2(int argc, char **argv)
   ed25519_public_key_t intro_auth_pubkey;
   curve25519_keypair_t client_ephemeral_enc_keypair;
   curve25519_public_key_t service_ephemeral_rend_pubkey;
-  uint8_t subcredential[DIGEST256_LEN];
+  hs_subcredential_t subcredential;
 
   /* Output */
   hs_ntor_rend_cell_keys_t hs_ntor_rend_cell_keys;
@@ -201,7 +201,7 @@ client2(int argc, char **argv)
          CURVE25519_SECKEY_LEN);
   BASE16(4, intro_enc_pubkey.public_key, CURVE25519_PUBKEY_LEN);
   BASE16(5, service_ephemeral_rend_pubkey.public_key, CURVE25519_PUBKEY_LEN);
-  BASE16(6, subcredential, DIGEST256_LEN);
+  BASE16(6, subcredential.subcred, DIGEST256_LEN);
 
   /* Generate keypair */
   curve25519_public_key_generate(&client_ephemeral_enc_keypair.pubkey,
diff --git a/src/test/test_hs_ob.c b/src/test/test_hs_ob.c
index 37c57f795..848a488be 100644
--- a/src/test/test_hs_ob.c
+++ b/src/test/test_hs_ob.c
@@ -190,7 +190,7 @@ test_get_subcredentials(void *arg)
   ed25519_keypair_generate(&onion_addr_kp_1, 0);
   smartlist_add(config.ob_master_pubkeys, &onion_addr_kp_1.pubkey);
 
-  uint8_t *subcreds = NULL;
+  hs_subcredential_t *subcreds = NULL;
   size_t num = hs_ob_get_subcredentials(&config, &subcreds);
   tt_uint_op(num, OP_EQ, 3);
 
@@ -200,14 +200,14 @@ test_get_subcredentials(void *arg)
   const int steps[3] = {0, -1, 1};
 
   for (unsigned int i = 0; i < num; i++) {
-    uint8_t subcredential[DIGEST256_LEN];
+    hs_subcredential_t subcredential;
     ed25519_public_key_t blinded_pubkey;
     hs_build_blinded_pubkey(&onion_addr_kp_1.pubkey, NULL, 0, tp + steps[i],
                             &blinded_pubkey);
     hs_get_subcredential(&onion_addr_kp_1.pubkey, &blinded_pubkey,
-                         subcredential);
-    tt_mem_op(&(subcreds[i * sizeof(subcredential)]), OP_EQ, subcredential,
-              sizeof(subcredential));
+                         &subcredential);
+    tt_mem_op(subcreds[i].subcred, OP_EQ, subcredential.subcred,
+              SUBCRED_LEN);
   }
 
  done:
@@ -228,4 +228,3 @@ struct testcase_t hs_ob_tests[] = {
 
   END_OF_TESTCASES
 };
-





More information about the tor-commits mailing list