123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- /* Copyright (c) 2017, The Tor Project, Inc. */
- /* See LICENSE for licensing information */
- /**
- * \file hs_cell.c
- * \brief Hidden service API for cell creation and handling.
- **/
- #include "or.h"
- #include "rendservice.h"
- #include "hs_cell.h"
- /* Trunnel. */
- #include "hs/cell_common.h"
- #include "hs/cell_establish_intro.h"
- /* Build a legacy ESTABLISH_INTRO cell with the given circuit nonce and RSA
- * encryption key. The encoded cell is put in cell_out that MUST at least be
- * of the size of RELAY_PAYLOAD_SIZE. Return the encoded cell length on
- * success else a negative value and cell_out is untouched. */
- static ssize_t
- build_legacy_establish_intro(const char *circ_nonce, crypto_pk_t *enc_key,
- uint8_t *cell_out)
- {
- ssize_t cell_len;
- char buf[RELAY_PAYLOAD_SIZE] = {0};
- tor_assert(circ_nonce);
- tor_assert(enc_key);
- tor_assert(cell_out);
- cell_len = rend_service_encode_establish_intro_cell(buf, sizeof(buf),
- enc_key, circ_nonce);
- tor_assert(cell_len <= RELAY_PAYLOAD_SIZE);
- if (cell_len >= 0) {
- memcpy(cell_out, buf, cell_len);
- }
- return cell_len;
- }
- /* ========== */
- /* Public API */
- /* ========== */
- /* Build an ESTABLISH_INTRO cell with the given circuit nonce and intro point
- * object. The encoded cell is put in cell_out that MUST at least be of the
- * size of RELAY_PAYLOAD_SIZE. Return the encoded cell length on success else
- * a negative value and cell_out is untouched. This function also supports
- * legacy cell creation. */
- ssize_t
- hs_cell_build_establish_intro(const char *circ_nonce,
- const hs_service_intro_point_t *ip,
- uint8_t *cell_out)
- {
- ssize_t cell_len = -1;
- uint16_t sig_len = ED25519_SIG_LEN;
- trn_cell_extension_t *ext;
- trn_cell_establish_intro_t *cell = NULL;
- tor_assert(circ_nonce);
- tor_assert(ip);
- /* Quickly handle the legacy IP. */
- if (ip->base.is_only_legacy) {
- tor_assert(ip->legacy_key);
- cell_len = build_legacy_establish_intro(circ_nonce, ip->legacy_key,
- cell_out);
- tor_assert(cell_len <= RELAY_PAYLOAD_SIZE);
- /* Success or not we are done here. */
- goto done;
- }
- /* Set extension data. None used here. */
- ext = trn_cell_extension_new();
- trn_cell_extension_set_num(ext, 0);
- cell = trn_cell_establish_intro_new();
- trn_cell_establish_intro_set_extensions(cell, ext);
- /* Set signature size. Array is then allocated in the cell. We need to do
- * this early so we can use trunnel API to get the signature length. */
- trn_cell_establish_intro_set_sig_len(cell, sig_len);
- trn_cell_establish_intro_setlen_sig(cell, sig_len);
- /* Set AUTH_KEY_TYPE: 2 means ed25519 */
- trn_cell_establish_intro_set_auth_key_type(cell,
- HS_INTRO_AUTH_KEY_TYPE_ED25519);
- /* Set AUTH_KEY and AUTH_KEY_LEN field. Must also set byte-length of
- * AUTH_KEY to match */
- {
- uint16_t auth_key_len = ED25519_PUBKEY_LEN;
- trn_cell_establish_intro_set_auth_key_len(cell, auth_key_len);
- trn_cell_establish_intro_setlen_auth_key(cell, auth_key_len);
- /* We do this call _after_ setting the length because it's reallocated at
- * that point only. */
- uint8_t *auth_key_ptr = trn_cell_establish_intro_getarray_auth_key(cell);
- memcpy(auth_key_ptr, ip->auth_key_kp.pubkey.pubkey, auth_key_len);
- }
- /* Calculate HANDSHAKE_AUTH field (MAC). */
- {
- ssize_t tmp_cell_enc_len = 0;
- ssize_t tmp_cell_mac_offset =
- sig_len + sizeof(cell->sig_len) +
- trn_cell_establish_intro_getlen_handshake_mac(cell);
- uint8_t tmp_cell_enc[RELAY_PAYLOAD_SIZE] = {0};
- uint8_t mac[TRUNNEL_SHA3_256_LEN], *handshake_ptr;
- /* We first encode the current fields we have in the cell so we can
- * compute the MAC using the raw bytes. */
- tmp_cell_enc_len = trn_cell_establish_intro_encode(tmp_cell_enc,
- sizeof(tmp_cell_enc),
- cell);
- if (BUG(tmp_cell_enc_len < 0)) {
- goto done;
- }
- /* Sanity check. */
- tor_assert(tmp_cell_enc_len > tmp_cell_mac_offset);
- /* Circuit nonce is always DIGEST_LEN according to tor-spec.txt. */
- crypto_mac_sha3_256(mac, sizeof(mac),
- (uint8_t *) circ_nonce, DIGEST_LEN,
- tmp_cell_enc, tmp_cell_enc_len - tmp_cell_mac_offset);
- handshake_ptr = trn_cell_establish_intro_getarray_handshake_mac(cell);
- memcpy(handshake_ptr, mac, sizeof(mac));
- }
- /* Calculate the cell signature SIG. */
- {
- ssize_t tmp_cell_enc_len = 0;
- ssize_t tmp_cell_sig_offset = (sig_len + sizeof(cell->sig_len));
- uint8_t tmp_cell_enc[RELAY_PAYLOAD_SIZE] = {0}, *sig_ptr;
- ed25519_signature_t sig;
- /* We first encode the current fields we have in the cell so we can
- * compute the signature from the raw bytes of the cell. */
- tmp_cell_enc_len = trn_cell_establish_intro_encode(tmp_cell_enc,
- sizeof(tmp_cell_enc),
- cell);
- if (BUG(tmp_cell_enc_len < 0)) {
- goto done;
- }
- if (ed25519_sign_prefixed(&sig, tmp_cell_enc,
- tmp_cell_enc_len - tmp_cell_sig_offset,
- ESTABLISH_INTRO_SIG_PREFIX, &ip->auth_key_kp)) {
- log_warn(LD_BUG, "Unable to make signature for ESTABLISH_INTRO cell.");
- goto done;
- }
- /* Copy the signature into the cell. */
- sig_ptr = trn_cell_establish_intro_getarray_sig(cell);
- memcpy(sig_ptr, sig.sig, sig_len);
- }
- /* Encode the cell. Can't be bigger than a standard cell. */
- cell_len = trn_cell_establish_intro_encode(cell_out, RELAY_PAYLOAD_SIZE,
- cell);
- done:
- trn_cell_establish_intro_free(cell);
- return cell_len;
- }
|