Tor 0.4.9.0-alpha-dev
Macros | Functions
onion_ntor_v3.c File Reference

Implements the version 3 ntor handshake as first specified in proposal 332. More...

#include "orconfig.h"
#include "core/crypto/onion_ntor_v3.h"
#include "lib/arch/bytes.h"
#include "lib/crypt_ops/crypto_digest.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/crypto_util.h"
#include "lib/ctime/di_ops.h"
#include "lib/log/util_bug.h"
#include <string.h>

Go to the source code of this file.

Macros

#define ONION_NTOR_V3_PRIVATE
 
#define PROTOID   "ntor3-curve25519-sha3_256-1"
 
#define TWEAK(A)   (PROTOID ":" A)
 
#define T_MSGKDF   TWEAK("kdf_phase1")
 
#define T_MSGMAC   TWEAK("msg_mac")
 
#define T_KEY_SEED   TWEAK("key_seed")
 
#define T_VERIFY   TWEAK("verify")
 
#define T_FINAL   TWEAK("kdf_final")
 
#define T_AUTH   TWEAK("auth_final")
 
#define xof_add(xof, data, len)   crypto_xof_add_bytes((xof), (data), (len))
 
#define xof_add_tweak(d, s)   xof_add_encap((d), (const uint8_t *)(s), strlen(s))
 
#define d_add_tweak(d, s)   d_add_encap((d), (const uint8_t *)(s), strlen(s))
 
#define ADD2(s, len)
 
#define ADD2_ENCAP(s, len)
 

Functions

static void xof_add_encap (crypto_xof_t *xof, const uint8_t *data, size_t len)
 
static void d_add (crypto_digest_t *digest, const uint8_t *data, size_t len)
 
static void d_add_encap (crypto_digest_t *digest, const uint8_t *data, size_t len)
 
static void push (uint8_t **ptr, const uint8_t *endptr, const uint8_t *data, size_t len)
 
void ntor3_handshake_state_free_ (ntor3_handshake_state_t *state)
 
int onion_skin_ntor3_create (const ed25519_public_key_t *relay_id, const curve25519_public_key_t *relay_key, const uint8_t *verification, const size_t verification_len, const uint8_t *message, const size_t message_len, ntor3_handshake_state_t **handshake_state_out, uint8_t **onion_skin_out, size_t *onion_skin_len_out)
 
STATIC int onion_skin_ntor3_create_nokeygen (const curve25519_keypair_t *client_keypair, const ed25519_public_key_t *relay_id, const curve25519_public_key_t *relay_key, const uint8_t *verification, const size_t verification_len, const uint8_t *message, const size_t message_len, ntor3_handshake_state_t **handshake_state_out, uint8_t **onion_skin_out, size_t *onion_skin_len_out)
 
int onion_ntor3_client_handshake (const ntor3_handshake_state_t *handshake_state, const uint8_t *handshake_reply, size_t reply_len, const uint8_t *verification, size_t verification_len, uint8_t *keys_out, size_t keys_out_len, uint8_t **message_out, size_t *message_len_out)
 
void ntor3_server_handshake_state_free_ (ntor3_server_handshake_state_t *state)
 
int onion_skin_ntor3_server_handshake_part1 (const di_digest256_map_t *private_keys, const curve25519_keypair_t *junk_key, const ed25519_public_key_t *my_id, const uint8_t *client_handshake, size_t client_handshake_len, const uint8_t *verification, size_t verification_len, uint8_t **client_message_out, size_t *client_message_len_out, ntor3_server_handshake_state_t **state_out)
 
int onion_skin_ntor3_server_handshake_part2 (const ntor3_server_handshake_state_t *state, const uint8_t *verification, size_t verification_len, const uint8_t *server_message, size_t server_message_len, uint8_t **handshake_out, size_t *handshake_len_out, uint8_t *keys_out, size_t keys_out_len)
 
STATIC int onion_skin_ntor3_server_handshake_part2_nokeygen (const curve25519_keypair_t *relay_keypair_y, const ntor3_server_handshake_state_t *state, const uint8_t *verification, size_t verification_len, const uint8_t *server_message, size_t server_message_len, uint8_t **handshake_out, size_t *handshake_len_out, uint8_t *keys_out, size_t keys_out_len)
 

Detailed Description

Implements the version 3 ntor handshake as first specified in proposal 332.

The v3 ntor handshake differs from the earlier versions (ntor and hs-ntor) primarily in that it allows the client to send an authenticated encrypted message as part of its onion skin, and allows the relay to send and encrypted authenticated reply as part of its response.

It also takes a "verification string" – the handshake cannot succeed unless both parties use the same value for their verification stream.

Definition in file onion_ntor_v3.c.

Macro Definition Documentation

◆ ADD2

#define ADD2 (   s,
  len 
)
Value:
STMT_BEGIN { \
d_add(ks, (s),(len)); d_add(v, (s), (len)); \
} STMT_END
static void d_add(crypto_digest_t *digest, const uint8_t *data, size_t len)
Definition: onion_ntor_v3.c:77

◆ ADD2_ENCAP

#define ADD2_ENCAP (   s,
  len 
)
Value:
STMT_BEGIN { \
d_add_encap(ks, (s),(len)); d_add_encap(v, (s), (len)); \
} STMT_END
static void d_add_encap(crypto_digest_t *digest, const uint8_t *data, size_t len)
Definition: onion_ntor_v3.c:88

◆ d_add_tweak

#define d_add_tweak (   d,
 
)    d_add_encap((d), (const uint8_t *)(s), strlen(s))

Add an encapsulated tweak to the provided digest.

Definition at line 97 of file onion_ntor_v3.c.

◆ ONION_NTOR_V3_PRIVATE

#define ONION_NTOR_V3_PRIVATE

Definition at line 21 of file onion_ntor_v3.c.

◆ PROTOID

#define PROTOID   "ntor3-curve25519-sha3_256-1"

Definition at line 37 of file onion_ntor_v3.c.

◆ T_AUTH

#define T_AUTH   TWEAK("auth_final")

Definition at line 45 of file onion_ntor_v3.c.

◆ T_FINAL

#define T_FINAL   TWEAK("kdf_final")

Definition at line 44 of file onion_ntor_v3.c.

◆ T_KEY_SEED

#define T_KEY_SEED   TWEAK("key_seed")

Definition at line 42 of file onion_ntor_v3.c.

◆ T_MSGKDF

#define T_MSGKDF   TWEAK("kdf_phase1")

Definition at line 40 of file onion_ntor_v3.c.

◆ T_MSGMAC

#define T_MSGMAC   TWEAK("msg_mac")

Definition at line 41 of file onion_ntor_v3.c.

◆ T_VERIFY

#define T_VERIFY   TWEAK("verify")

Definition at line 43 of file onion_ntor_v3.c.

◆ TWEAK

#define TWEAK (   A)    (PROTOID ":" A)

Definition at line 38 of file onion_ntor_v3.c.

◆ xof_add

#define xof_add (   xof,
  data,
  len 
)    crypto_xof_add_bytes((xof), (data), (len))

Add len bytes of data as input to the provided xof.

(This is provided just for abbreviation).

Definition at line 52 of file onion_ntor_v3.c.

◆ xof_add_tweak

#define xof_add_tweak (   d,
 
)    xof_add_encap((d), (const uint8_t *)(s), strlen(s))

Add an encapsulated tweak to the provided xof.

Definition at line 69 of file onion_ntor_v3.c.

Function Documentation

◆ d_add()

static void d_add ( crypto_digest_t digest,
const uint8_t *  data,
size_t  len 
)
static

Add len bytes of data to the provided digest.

This is provided as an abbreviation, and to get the types right.

Definition at line 77 of file onion_ntor_v3.c.

Referenced by d_add_encap().

◆ d_add_encap()

static void d_add_encap ( crypto_digest_t digest,
const uint8_t *  data,
size_t  len 
)
static

Add len bytes of data to the provided digest, prefixed with the encoded length.

This is equivalent to ENCAP(data) from the spec.

Definition at line 88 of file onion_ntor_v3.c.

◆ ntor3_handshake_state_free_()

void ntor3_handshake_state_free_ ( ntor3_handshake_state_t state)

Helper: Drop storage held by state, after wiping it.

Definition at line 118 of file onion_ntor_v3.c.

◆ ntor3_server_handshake_state_free_()

void ntor3_server_handshake_state_free_ ( ntor3_server_handshake_state_t state)

Wipe a server handshake state, and release the storage it holds.

Definition at line 434 of file onion_ntor_v3.c.

◆ onion_ntor3_client_handshake()

int onion_ntor3_client_handshake ( const ntor3_handshake_state_t handshake_state,
const uint8_t *  handshake_reply,
size_t  reply_len,
const uint8_t *  verification,
size_t  verification_len,
uint8_t *  keys_out,
size_t  keys_out_len,
uint8_t **  message_out,
size_t *  message_len_out 
)

Complete a client-side v3 ntor handshake.

Takes a handshake_state returned earlier by onion_skin_ntor3_create(), and the relay's reply to that handshake (reply_len bytes at handshake_reply). Also takes a verification string (verification_len bytes at verification).

Returns 0 on success and -1 on failure. On success, generates key_len bytes of key material into the provided keys_out buffer, and sets message_out to the message that the relay sent in reply to our message (and sets message_out_len to that message's length).

Definition at line 298 of file onion_ntor_v3.c.

◆ onion_skin_ntor3_create()

int onion_skin_ntor3_create ( const ed25519_public_key_t relay_id,
const curve25519_public_key_t relay_key,
const uint8_t *  verification,
const size_t  verification_len,
const uint8_t *  message,
const size_t  message_len,
ntor3_handshake_state_t **  handshake_state_out,
uint8_t **  onion_skin_out,
size_t *  onion_skin_len_out 
)

Perform a client-side v3 ntor handshake with a given relay.

As inputs this function takes the relay's Ed25519 identity (relay_id), the relay's current ntor onion key (relay_key), a verification string (verification_len bytes at verification), and a message to send as part of the handshake (message_len bytes at message).

The message will be encrypted and authenticated to the relay, but will not receive the same forward secrecy as the rest of the handshake. We should not put any super-confidential data in it.

The handshake will only succeed if the relay uses the same verification string as we are using.

As outputs, this function returns 0 on success and -1 on failure. On success, it sets onion_skin_out and onion_skin_len_out to a newly allocated handshake message that the client can send as part of its CREATE2 or EXTEND2 cell. It also sets it sets handshake_state_out to a newly allocated handshake state object; the client needs to use this object to process the relay's eventual reply.

Definition at line 150 of file onion_ntor_v3.c.

◆ onion_skin_ntor3_create_nokeygen()

STATIC int onion_skin_ntor3_create_nokeygen ( const curve25519_keypair_t client_keypair,
const ed25519_public_key_t relay_id,
const curve25519_public_key_t relay_key,
const uint8_t *  verification,
const size_t  verification_len,
const uint8_t *  message,
const size_t  message_len,
ntor3_handshake_state_t **  handshake_state_out,
uint8_t **  onion_skin_out,
size_t *  onion_skin_len_out 
)

Like onion_skin_ntor3_create, but do not generate a new ephemeral keypair. Instead, take the ephemeral keypair (x,X) from client_keypair.

(Having a separate function for this lets us test the code for correct behavior.)

Definition at line 187 of file onion_ntor_v3.c.

Referenced by onion_skin_ntor3_create().

◆ onion_skin_ntor3_server_handshake_part1()

int onion_skin_ntor3_server_handshake_part1 ( const di_digest256_map_t private_keys,
const curve25519_keypair_t junk_key,
const ed25519_public_key_t my_id,
const uint8_t *  client_handshake,
size_t  client_handshake_len,
const uint8_t *  verification,
size_t  verification_len,
uint8_t **  client_message_out,
size_t *  client_message_len_out,
ntor3_server_handshake_state_t **  state_out 
)

As a relay, start handling a client's v3 ntor handshake.

This function performs the first half of the handshake, up to the point where the client's message is decoded. After calling it, the relay should decide how and whether to reply to the client's message, compose its reply, and call onion_skin_ntor3_server_handshake_part2.

It takes as input a map of the relay's known onion keys in private_keys, along with a fake junk_key to use if there is a complete mismatch. It takes the relay's ed25519 identity in my_id, along with the client's handshake message (client_handshake_len bytes in client_handshake), and a verification string (verification_len bytes in verification).

Return 0 on success, and -1 on failure. On success, sets client_message_out to a newly allocated string holding the plaintext of the message that the client sent as part of its handshake, and client_message_out_len to its length. Also sets state_out to a newly allocated state object holding the intermediate computation for this handshake.

Definition at line 465 of file onion_ntor_v3.c.

◆ onion_skin_ntor3_server_handshake_part2()

int onion_skin_ntor3_server_handshake_part2 ( const ntor3_server_handshake_state_t state,
const uint8_t *  verification,
size_t  verification_len,
const uint8_t *  server_message,
size_t  server_message_len,
uint8_t **  handshake_out,
size_t *  handshake_len_out,
uint8_t *  keys_out,
size_t  keys_out_len 
)

Finish the relay side of an ntor v3 handshake.

The relay calls this function after it has decided to respond to the client's original encrypted message. This function receives the relay's message in server_message and its length in server_message_len, and completes the handshake.

Returns 0 on success and -1 on failure. On success, stores the newly allocated handshake for the relay to send in handshake_out, and its length in handshake_len_out. Stores keys_out_len bytes of generated keys in the provided buffer at keys_out.

Definition at line 612 of file onion_ntor_v3.c.

◆ onion_skin_ntor3_server_handshake_part2_nokeygen()

STATIC int onion_skin_ntor3_server_handshake_part2_nokeygen ( const curve25519_keypair_t relay_keypair_y,
const ntor3_server_handshake_state_t state,
const uint8_t *  verification,
size_t  verification_len,
const uint8_t *  server_message,
size_t  server_message_len,
uint8_t **  handshake_out,
size_t *  handshake_len_out,
uint8_t *  keys_out,
size_t  keys_out_len 
)

Like onion_skin_ntor3_server_handshake_part2, but do not generate an ephemeral (y,Y) keypair.

Instead, this function takes that keypair as relay_keypair_y.

(Having a separate function for this lets us test the code for correct behavior.)

Definition at line 652 of file onion_ntor_v3.c.

Referenced by onion_skin_ntor3_server_handshake_part2().

◆ push()

static void push ( uint8_t **  ptr,
const uint8_t *  endptr,
const uint8_t *  data,
size_t  len 
)
static

Helper: copy len bytes of data onto *ptr, and advance ptr forward by len bytes.

Asserts that ptr will not be advanced beyond endptr.

Definition at line 106 of file onion_ntor_v3.c.

◆ xof_add_encap()

static void xof_add_encap ( crypto_xof_t xof,
const uint8_t *  data,
size_t  len 
)
static

Add len bytes of data as input to the provided xof, prefixed with an encoding of the length.

This is equivalent to ENCAP(data) in the spec.

Definition at line 60 of file onion_ntor_v3.c.