mirror of
https://github.com/aljazceru/lightning.git
synced 2026-02-23 15:04:19 +01:00
common: use struct onionreply.
This makes it clear we're dealing with a message which is a wrapped error reply (needing unwrap_onionreply), not an already-wrapped one. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#include <ccan/crypto/shachain/shachain.h>
|
||||
#include <common/htlc_wire.h>
|
||||
#include <common/memleak.h>
|
||||
#include <common/onionreply.h>
|
||||
#include <wire/wire.h>
|
||||
|
||||
/* FIXME: We could adapt tools/generate-wire.py to generate structures
|
||||
@@ -26,8 +27,8 @@ void towire_fulfilled_htlc(u8 **pptr, const struct fulfilled_htlc *fulfilled)
|
||||
void towire_failed_htlc(u8 **pptr, const struct failed_htlc *failed)
|
||||
{
|
||||
/* Only one can be set. */
|
||||
assert(failed->failcode || tal_count(failed->failreason));
|
||||
assert(!failed->failcode || !tal_count(failed->failreason));
|
||||
assert(failed->failcode || failed->failreason);
|
||||
assert(!failed->failcode || !failed->failreason);
|
||||
towire_u64(pptr, failed->id);
|
||||
towire_u16(pptr, failed->failcode);
|
||||
if (failed->failcode & UPDATE) {
|
||||
@@ -37,9 +38,7 @@ void towire_failed_htlc(u8 **pptr, const struct failed_htlc *failed)
|
||||
assert(!failed->scid);
|
||||
if (!failed->failcode) {
|
||||
assert(failed->failreason);
|
||||
towire_u16(pptr, tal_count(failed->failreason));
|
||||
towire_u8_array(pptr, failed->failreason,
|
||||
tal_count(failed->failreason));
|
||||
towire_onionreply(pptr, failed->failreason);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -98,12 +97,8 @@ struct failed_htlc *fromwire_failed_htlc(const tal_t *ctx, const u8 **cursor, si
|
||||
failed->id = fromwire_u64(cursor, max);
|
||||
failed->failcode = fromwire_u16(cursor, max);
|
||||
if (failed->failcode == 0) {
|
||||
u16 failreason_len;
|
||||
failed->scid = NULL;
|
||||
failreason_len = fromwire_u16(cursor, max);
|
||||
failed->failreason = tal_arr(failed, u8, failreason_len);
|
||||
fromwire_u8_array(cursor, max, failed->failreason,
|
||||
failreason_len);
|
||||
failed->failreason = fromwire_onionreply(failed, cursor, max);
|
||||
} else {
|
||||
failed->failreason = NULL;
|
||||
if (failed->failcode & UPDATE) {
|
||||
|
||||
@@ -29,7 +29,7 @@ struct failed_htlc {
|
||||
u64 id;
|
||||
/* Either this is 0 and failreason non-NULL, or vice versa. */
|
||||
enum onion_type failcode;
|
||||
u8 *failreason;
|
||||
const struct onionreply *failreason;
|
||||
/* Non-NULL if failcode & UPDATE */
|
||||
struct short_channel_id *scid;
|
||||
};
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <ccan/mem/mem.h>
|
||||
#include <common/node_id.h>
|
||||
#include <common/onion.h>
|
||||
#include <common/onionreply.h>
|
||||
#include <common/sphinx.h>
|
||||
#include <common/utils.h>
|
||||
|
||||
@@ -529,12 +530,14 @@ struct route_step *process_onionpacket(
|
||||
return step;
|
||||
}
|
||||
|
||||
u8 *create_onionreply(const tal_t *ctx, const struct secret *shared_secret,
|
||||
const u8 *failure_msg)
|
||||
struct onionreply *create_onionreply(const tal_t *ctx,
|
||||
const struct secret *shared_secret,
|
||||
const u8 *failure_msg)
|
||||
{
|
||||
size_t msglen = tal_count(failure_msg);
|
||||
size_t padlen = ONION_REPLY_SIZE - msglen;
|
||||
u8 *reply = tal_arr(ctx, u8, 0), *payload = tal_arr(ctx, u8, 0);
|
||||
struct onionreply *reply = tal(ctx, struct onionreply);
|
||||
u8 *payload = tal_arr(ctx, u8, 0);
|
||||
u8 key[KEY_LEN];
|
||||
u8 hmac[HMAC_SIZE];
|
||||
|
||||
@@ -574,21 +577,23 @@ u8 *create_onionreply(const tal_t *ctx, const struct secret *shared_secret,
|
||||
generate_key(key, "um", 2, shared_secret->data);
|
||||
|
||||
compute_hmac(hmac, payload, tal_count(payload), key, KEY_LEN);
|
||||
towire(&reply, hmac, sizeof(hmac));
|
||||
reply->contents = tal_arr(reply, u8, 0),
|
||||
towire(&reply->contents, hmac, sizeof(hmac));
|
||||
|
||||
towire(&reply, payload, tal_count(payload));
|
||||
towire(&reply->contents, payload, tal_count(payload));
|
||||
tal_free(payload);
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
u8 *wrap_onionreply(const tal_t *ctx,
|
||||
const struct secret *shared_secret, const u8 *reply)
|
||||
struct onionreply *wrap_onionreply(const tal_t *ctx,
|
||||
const struct secret *shared_secret,
|
||||
const struct onionreply *reply)
|
||||
{
|
||||
u8 key[KEY_LEN];
|
||||
size_t streamlen = tal_count(reply);
|
||||
size_t streamlen = tal_count(reply->contents);
|
||||
u8 stream[streamlen];
|
||||
u8 *result = tal_arr(ctx, u8, streamlen);
|
||||
struct onionreply *result = tal(ctx, struct onionreply);
|
||||
|
||||
/* BOLT #4:
|
||||
*
|
||||
@@ -600,39 +605,43 @@ u8 *wrap_onionreply(const tal_t *ctx,
|
||||
*/
|
||||
generate_key(key, "ammag", 5, shared_secret->data);
|
||||
generate_cipher_stream(stream, key, streamlen);
|
||||
xorbytes(result, stream, reply, streamlen);
|
||||
result->contents = tal_arr(result, u8, streamlen);
|
||||
xorbytes(result->contents, stream, reply->contents, streamlen);
|
||||
return result;
|
||||
}
|
||||
|
||||
u8 *unwrap_onionreply(const tal_t *ctx,
|
||||
const struct secret *shared_secrets,
|
||||
const int numhops, const u8 *reply,
|
||||
const int numhops,
|
||||
const struct onionreply *reply,
|
||||
int *origin_index)
|
||||
{
|
||||
u8 *msg = tal_arr(tmpctx, u8, tal_count(reply)), *final;
|
||||
struct onionreply *r;
|
||||
u8 key[KEY_LEN], hmac[HMAC_SIZE];
|
||||
const u8 *cursor;
|
||||
u8 *final;
|
||||
size_t max;
|
||||
u16 msglen;
|
||||
|
||||
if (tal_count(reply) != ONION_REPLY_SIZE + sizeof(hmac) + 4) {
|
||||
if (tal_count(reply->contents) != ONION_REPLY_SIZE + sizeof(hmac) + 4) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(msg, reply, tal_count(reply));
|
||||
r = new_onionreply(tmpctx, reply->contents);
|
||||
*origin_index = -1;
|
||||
|
||||
for (int i = 0; i < numhops; i++) {
|
||||
/* Since the encryption is just XORing with the cipher
|
||||
* stream encryption is identical to decryption */
|
||||
msg = wrap_onionreply(tmpctx, &shared_secrets[i], msg);
|
||||
r = wrap_onionreply(tmpctx, &shared_secrets[i], r);
|
||||
|
||||
/* Check if the HMAC matches, this means that this is
|
||||
* the origin */
|
||||
generate_key(key, "um", 2, shared_secrets[i].data);
|
||||
compute_hmac(hmac, msg + sizeof(hmac),
|
||||
tal_count(msg) - sizeof(hmac), key, KEY_LEN);
|
||||
if (memcmp(hmac, msg, sizeof(hmac)) == 0) {
|
||||
compute_hmac(hmac, r->contents + sizeof(hmac),
|
||||
tal_count(r->contents) - sizeof(hmac),
|
||||
key, KEY_LEN);
|
||||
if (memcmp(hmac, r->contents, sizeof(hmac)) == 0) {
|
||||
*origin_index = i;
|
||||
break;
|
||||
}
|
||||
@@ -641,8 +650,8 @@ u8 *unwrap_onionreply(const tal_t *ctx,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cursor = msg + sizeof(hmac);
|
||||
max = tal_count(msg) - sizeof(hmac);
|
||||
cursor = r->contents + sizeof(hmac);
|
||||
max = tal_count(r->contents) - sizeof(hmac);
|
||||
msglen = fromwire_u16(&cursor, &max);
|
||||
|
||||
if (msglen > ONION_REPLY_SIZE) {
|
||||
@@ -650,7 +659,7 @@ u8 *unwrap_onionreply(const tal_t *ctx,
|
||||
}
|
||||
|
||||
final = tal_arr(ctx, u8, msglen);
|
||||
fromwire(&cursor, &max, final, msglen);
|
||||
|
||||
if (!fromwire(&cursor, &max, final, msglen))
|
||||
return tal_free(final);
|
||||
return final;
|
||||
}
|
||||
|
||||
@@ -164,8 +164,9 @@ enum onion_type parse_onionpacket(const u8 *src,
|
||||
* HMAC
|
||||
* @failure_msg: message (must support tal_len)
|
||||
*/
|
||||
u8 *create_onionreply(const tal_t *ctx, const struct secret *shared_secret,
|
||||
const u8 *failure_msg);
|
||||
struct onionreply *create_onionreply(const tal_t *ctx,
|
||||
const struct secret *shared_secret,
|
||||
const u8 *failure_msg);
|
||||
|
||||
/**
|
||||
* wrap_onionreply - Add another encryption layer to the reply.
|
||||
@@ -175,8 +176,9 @@ u8 *create_onionreply(const tal_t *ctx, const struct secret *shared_secret,
|
||||
* encryption.
|
||||
* @reply: the reply to wrap
|
||||
*/
|
||||
u8 *wrap_onionreply(const tal_t *ctx, const struct secret *shared_secret,
|
||||
const u8 *reply);
|
||||
struct onionreply *wrap_onionreply(const tal_t *ctx,
|
||||
const struct secret *shared_secret,
|
||||
const struct onionreply *reply);
|
||||
|
||||
/**
|
||||
* unwrap_onionreply - Remove layers, check integrity and parse reply
|
||||
@@ -186,10 +188,13 @@ u8 *wrap_onionreply(const tal_t *ctx, const struct secret *shared_secret,
|
||||
* @numhops: path length and number of shared_secrets provided
|
||||
* @reply: the incoming reply
|
||||
* @origin_index: the index in the path where the reply came from (-1 if unknown)
|
||||
*
|
||||
* Reverses create_onionreply and wrap_onionreply.
|
||||
*/
|
||||
u8 *unwrap_onionreply(const tal_t *ctx,
|
||||
const struct secret *shared_secrets,
|
||||
const int numhops, const u8 *reply,
|
||||
const int numhops,
|
||||
const struct onionreply *reply,
|
||||
int *origin_index);
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "../onion.c"
|
||||
#include "../onionreply.c"
|
||||
#include "../sphinx.c"
|
||||
#include <secp256k1.h>
|
||||
#include <ccan/opt/opt.h>
|
||||
@@ -61,8 +62,8 @@ static struct secret secret_from_hex(const char *hex)
|
||||
static void run_unit_tests(void)
|
||||
{
|
||||
u8 *oreply;
|
||||
struct onionreply *reply;
|
||||
int origin_index;
|
||||
u8 *reply;
|
||||
u8 *raw = tal_hexdata(tmpctx, "2002", 4);
|
||||
|
||||
/* Shared secrets we already have from the forward path */
|
||||
@@ -158,10 +159,10 @@ static void run_unit_tests(void)
|
||||
|
||||
reply = create_onionreply(tmpctx, &ss[4], raw);
|
||||
for (int i = 4; i >= 0; i--) {
|
||||
printf("input_packet %s\n", tal_hex(tmpctx, reply));
|
||||
printf("input_packet %s\n", tal_hex(tmpctx, reply->contents));
|
||||
reply = wrap_onionreply(tmpctx, &ss[i], reply);
|
||||
printf("obfuscated_packet %s\n", tal_hex(tmpctx, reply));
|
||||
assert(memcmp(reply, intermediates[i], tal_count(reply)) == 0);
|
||||
printf("obfuscated_packet %s\n", tal_hex(tmpctx, reply->contents));
|
||||
assert(memcmp(reply->contents, intermediates[i], tal_count(reply->contents)) == 0);
|
||||
}
|
||||
|
||||
oreply = unwrap_onionreply(tmpctx, ss, 5, reply, &origin_index);
|
||||
|
||||
Reference in New Issue
Block a user