Tor  0.4.7.0-alpha-dev
Macros | Functions
hs_ntor.c File Reference

Implements the ntor variant used in Tor hidden services. More...

#include "core/or/or.h"
#include "lib/crypt_ops/crypto_util.h"
#include "lib/crypt_ops/crypto_curve25519.h"
#include "lib/crypt_ops/crypto_ed25519.h"
#include "core/crypto/hs_ntor.h"

Go to the source code of this file.

Macros

#define PROTOID   "tor-hs-ntor-curve25519-sha3-256-1"
 
#define PROTOID_LEN   (sizeof(PROTOID) - 1)
 
#define SERVER_STR   "Server"
 
#define SERVER_STR_LEN   (sizeof(SERVER_STR) - 1)
 
#define T_HSENC   PROTOID ":hs_key_extract"
 
#define T_HSENC_LEN   (sizeof(T_HSENC) - 1)
 
#define T_HSVERIFY   PROTOID ":hs_verify"
 
#define T_HSMAC   PROTOID ":hs_mac"
 
#define M_HSEXPAND   PROTOID ":hs_key_expand"
 
#define M_HSEXPAND_LEN   (sizeof(M_HSEXPAND) - 1)
 
#define APPEND(ptr, inp, len)
 
#define REND_SECRET_HS_INPUT_LEN
 
#define REND_AUTH_INPUT_LEN
 
#define INTRO_SECRET_HS_INPUT_LEN
 
#define INFO_BLOB_LEN   (M_HSEXPAND_LEN + DIGEST256_LEN)
 
#define KDF_INPUT_LEN   (INTRO_SECRET_HS_INPUT_LEN + T_HSENC_LEN + INFO_BLOB_LEN)
 
#define NTOR_KEY_EXPANSION_KDF_INPUT_LEN   (DIGEST256_LEN + M_HSEXPAND_LEN)
 

Functions

static int get_rendezvous1_key_material (const uint8_t *rend_secret_hs_input, const ed25519_public_key_t *intro_auth_pubkey, const curve25519_public_key_t *intro_enc_pubkey, const curve25519_public_key_t *service_ephemeral_rend_pubkey, const curve25519_public_key_t *client_ephemeral_enc_pubkey, hs_ntor_rend_cell_keys_t *hs_ntor_rend_cell_keys_out)
 
static void get_introduce1_key_material (const uint8_t *secret_input, const hs_subcredential_t *subcredential, hs_ntor_intro_cell_keys_t *hs_ntor_intro_cell_keys_out)
 
static void get_intro_secret_hs_input (const uint8_t *dh_result, const ed25519_public_key_t *intro_auth_pubkey, const curve25519_public_key_t *client_ephemeral_enc_pubkey, const curve25519_public_key_t *intro_enc_pubkey, uint8_t *secret_input_out)
 
static void get_rend_secret_hs_input (const uint8_t *dh_result1, const uint8_t *dh_result2, const ed25519_public_key_t *intro_auth_pubkey, const curve25519_public_key_t *intro_enc_pubkey, const curve25519_public_key_t *client_ephemeral_enc_pubkey, const curve25519_public_key_t *service_ephemeral_rend_pubkey, uint8_t *rend_secret_hs_input_out)
 
int 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 hs_subcredential_t *subcredential, hs_ntor_intro_cell_keys_t *hs_ntor_intro_cell_keys_out)
 
int hs_ntor_client_get_rendezvous1_keys (const ed25519_public_key_t *intro_auth_pubkey, const curve25519_keypair_t *client_ephemeral_enc_keypair, const curve25519_public_key_t *intro_enc_pubkey, const curve25519_public_key_t *service_ephemeral_rend_pubkey, hs_ntor_rend_cell_keys_t *hs_ntor_rend_cell_keys_out)
 
int 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 hs_subcredential_t *subcredential, hs_ntor_intro_cell_keys_t *hs_ntor_intro_cell_keys_out)
 
int hs_ntor_service_get_introduce1_keys_multi (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, size_t n_subcredentials, const hs_subcredential_t *subcredentials, hs_ntor_intro_cell_keys_t *hs_ntor_intro_cell_keys_out)
 
int hs_ntor_service_get_rendezvous1_keys (const ed25519_public_key_t *intro_auth_pubkey, const curve25519_keypair_t *intro_enc_keypair, const curve25519_keypair_t *service_ephemeral_rend_keypair, const curve25519_public_key_t *client_ephemeral_enc_pubkey, hs_ntor_rend_cell_keys_t *hs_ntor_rend_cell_keys_out)
 
int hs_ntor_client_rendezvous2_mac_is_good (const hs_ntor_rend_cell_keys_t *hs_ntor_rend_cell_keys, const uint8_t *rcvd_mac)
 
int hs_ntor_circuit_key_expansion (const uint8_t *ntor_key_seed, size_t seed_len, uint8_t *keys_out, size_t keys_out_len)
 

Detailed Description

Implements the ntor variant used in Tor hidden services.

This module handles the variant of the ntor handshake that is documented in section [NTOR-WITH-EXTRA-DATA] of rend-spec-ng.txt .

The functions in this file provide an API that should be used when sending or receiving INTRODUCE1/RENDEZVOUS1 cells to generate the various key material required to create and handle those cells.

In the case of INTRODUCE1 it provides encryption and MAC keys to encode/decode the encrypted blob (see hs_ntor_intro_cell_keys_t). The relevant pub functions are hs_ntor_{client,service}_get_introduce1_keys().

In the case of RENDEZVOUS1 it calculates the MAC required to authenticate the cell, and also provides the key seed that is used to derive the crypto material for rendezvous encryption (see hs_ntor_rend_cell_keys_t). The relevant pub functions are hs_ntor_{client,service}_get_rendezvous1_keys(). It also provides a function (hs_ntor_circuit_key_expansion()) that does the rendezvous key expansion to setup end-to-end rend circuit keys.

Definition in file hs_ntor.c.

Macro Definition Documentation

◆ APPEND

#define APPEND (   ptr,
  inp,
  len 
)
Value:
STMT_BEGIN { \
memcpy(ptr, (inp), (len)); \
ptr += len; \
} STMT_END

Helper macro: copy len bytes from inp to ptr and advance ptr by the number of bytes copied. Stolen from onion_ntor.c

Definition at line 51 of file hs_ntor.c.

◆ INTRO_SECRET_HS_INPUT_LEN

#define INTRO_SECRET_HS_INPUT_LEN
Value:
CURVE25519_PUBKEY_LEN + CURVE25519_PUBKEY_LEN + PROTOID_LEN)
#define CURVE25519_OUTPUT_LEN
Definition: x25519_sizes.h:24
#define ED25519_PUBKEY_LEN
Definition: x25519_sizes.h:27
#define CURVE25519_PUBKEY_LEN
Definition: x25519_sizes.h:20

Length of secret_input = EXP(B,x) | AUTH_KEY | X | B | PROTOID

Definition at line 149 of file hs_ntor.c.

◆ REND_AUTH_INPUT_LEN

#define REND_AUTH_INPUT_LEN
Value:
CURVE25519_PUBKEY_LEN * 3 + PROTOID_LEN + SERVER_STR_LEN)
#define DIGEST256_LEN
Definition: digest_sizes.h:23

Definition at line 61 of file hs_ntor.c.

◆ REND_SECRET_HS_INPUT_LEN

#define REND_SECRET_HS_INPUT_LEN
Value:
ED25519_PUBKEY_LEN + CURVE25519_PUBKEY_LEN * 3 + PROTOID_LEN)

Definition at line 58 of file hs_ntor.c.

Function Documentation

◆ get_intro_secret_hs_input()

static void get_intro_secret_hs_input ( const uint8_t *  dh_result,
const ed25519_public_key_t intro_auth_pubkey,
const curve25519_public_key_t client_ephemeral_enc_pubkey,
const curve25519_public_key_t intro_enc_pubkey,
uint8_t *  secret_input_out 
)
static

Helper function: Calculate the 'intro_secret_hs_input' element used by the HS ntor handshake and place it in secret_input_out. This function is used by both client and service code.

For the client-side it looks like this:

    intro_secret_hs_input = EXP(B,x) | AUTH_KEY | X | B | PROTOID

whereas for the service-side it looks like this:

    intro_secret_hs_input = EXP(X,b) | AUTH_KEY | X | B | PROTOID

In this function, dh_result carries the EXP() result (and has size CURVE25519_OUTPUT_LEN) intro_auth_pubkey is AUTH_KEY, client_ephemeral_enc_pubkey is X, and intro_enc_pubkey is B.

Definition at line 225 of file hs_ntor.c.

Referenced by hs_ntor_service_get_introduce1_keys_multi().

◆ get_introduce1_key_material()

static void get_introduce1_key_material ( const uint8_t *  secret_input,
const hs_subcredential_t subcredential,
hs_ntor_intro_cell_keys_t hs_ntor_intro_cell_keys_out 
)
static

Helper function: Compute the part of the HS ntor handshake that generates key material for creating and handling INTRODUCE1 cells. Function used by both client and service. Specifically, calculate the following:

info = m_hsexpand | subcredential hs_keys = KDF(intro_secret_hs_input | t_hsenc | info, S_KEY_LEN+MAC_LEN) ENC_KEY = hs_keys[0:S_KEY_LEN] MAC_KEY = hs_keys[S_KEY_LEN:S_KEY_LEN+MAC_KEY_LEN]

where intro_secret_hs_input is secret_input (of size INTRO_SECRET_HS_INPUT_LEN), and subcredential is of size DIGEST256_LEN.

If everything went well, fill hs_ntor_intro_cell_keys_out with the necessary key material, and return 0.

Definition at line 172 of file hs_ntor.c.

Referenced by hs_ntor_service_get_introduce1_keys_multi().

◆ get_rend_secret_hs_input()

static void get_rend_secret_hs_input ( const uint8_t *  dh_result1,
const uint8_t *  dh_result2,
const ed25519_public_key_t intro_auth_pubkey,
const curve25519_public_key_t intro_enc_pubkey,
const curve25519_public_key_t client_ephemeral_enc_pubkey,
const curve25519_public_key_t service_ephemeral_rend_pubkey,
uint8_t *  rend_secret_hs_input_out 
)
static

Calculate the 'rend_secret_hs_input' element used by the HS ntor handshake and place it in rend_secret_hs_input_out. This function is used by both client and service code.

The computation on the client side is: rend_secret_hs_input = EXP(X,y) | EXP(X,b) | AUTH_KEY | B | X | Y | PROTOID whereas on the service side it is: rend_secret_hs_input = EXP(Y,x) | EXP(B,x) | AUTH_KEY | B | X | Y | PROTOID

where: dh_result1 and dh_result2 carry the two EXP() results (of size CURVE25519_OUTPUT_LEN) intro_auth_pubkey is AUTH_KEY, intro_enc_pubkey is B, client_ephemeral_enc_pubkey is X, and service_ephemeral_rend_pubkey is Y.

Definition at line 265 of file hs_ntor.c.

◆ get_rendezvous1_key_material()

static int get_rendezvous1_key_material ( const uint8_t *  rend_secret_hs_input,
const ed25519_public_key_t intro_auth_pubkey,
const curve25519_public_key_t intro_enc_pubkey,
const curve25519_public_key_t service_ephemeral_rend_pubkey,
const curve25519_public_key_t client_ephemeral_enc_pubkey,
hs_ntor_rend_cell_keys_t hs_ntor_rend_cell_keys_out 
)
static

Helper function: Compute the last part of the HS ntor handshake which derives key material necessary to create and handle RENDEZVOUS1 cells. Function used by both client and service. The actual calculations is as follows:

NTOR_KEY_SEED = MAC(rend_secret_hs_input, t_hsenc) verify = MAC(rend_secret_hs_input, t_hsverify) auth_input = verify | AUTH_KEY | B | Y | X | PROTOID | "Server" auth_input_mac = MAC(auth_input, t_hsmac)

where in the above, AUTH_KEY is intro_auth_pubkey, B is intro_enc_pubkey, Y is service_ephemeral_rend_pubkey, and X is client_ephemeral_enc_pubkey. The provided rend_secret_hs_input is of size REND_SECRET_HS_INPUT_LEN.

The final results of NTOR_KEY_SEED and auth_input_mac are placed in hs_ntor_rend_cell_keys_out. Return 0 if everything went fine.

Definition at line 82 of file hs_ntor.c.

◆ hs_ntor_circuit_key_expansion()

int hs_ntor_circuit_key_expansion ( const uint8_t *  ntor_key_seed,
size_t  seed_len,
uint8_t *  keys_out,
size_t  keys_out_len 
)

Given the rendezvous key seed in ntor_key_seed (of size DIGEST256_LEN), do the circuit key expansion as specified by section '4.2.1. Key expansion' and place the keys in keys_out (which must be of size HS_NTOR_KEY_EXPANSION_KDF_OUT_LEN).

Return 0 if things went well, else return -1.

Definition at line 615 of file hs_ntor.c.

◆ hs_ntor_client_rendezvous2_mac_is_good()

int hs_ntor_client_rendezvous2_mac_is_good ( const hs_ntor_rend_cell_keys_t hs_ntor_rend_cell_keys,
const uint8_t *  rcvd_mac 
)

Given a received RENDEZVOUS2 MAC in mac (of length DIGEST256_LEN), and the RENDEZVOUS1 key material in hs_ntor_rend_cell_keys, return 1 if the MAC is good, otherwise return 0.

Definition at line 594 of file hs_ntor.c.

◆ hs_ntor_service_get_introduce1_keys_multi()

int hs_ntor_service_get_introduce1_keys_multi ( 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,
size_t  n_subcredentials,
const hs_subcredential_t subcredentials,
hs_ntor_intro_cell_keys_t hs_ntor_intro_cell_keys_out 
)

As hs_ntor_service_get_introduce1_keys(), but take multiple subcredentials as input, and yield multiple sets of keys as output.

Definition at line 470 of file hs_ntor.c.