Skip to content

Commit a4c482d

Browse files
rustyrussellcdecker
authored andcommitted
common/sphinx: don't use fixed lengths anywhere.
1. Remove the very concept of ONION_REPLY_SIZE, instead make it a local variable in create_onionreply(). 2. Use the proper fromwire_ primitives in unwrap_onionreply() so we don't have to do explicit length checks. 3. Make fromwire_tal_arrn() return NULL if it fails to pull, instead of a zero-length allocation. Signed-off-by: Rusty Russell <[email protected]> Changelog-Fixed: Protocol: we now correctly decrypt non-256-length onion errors (we always forwarded them fine, now we actually can parse them).
1 parent fe1b285 commit a4c482d

File tree

3 files changed

+38
-39
lines changed

3 files changed

+38
-39
lines changed

common/sphinx.c

Lines changed: 36 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616

1717
#define BLINDING_FACTOR_SIZE 32
1818

19-
#define ONION_REPLY_SIZE 256
20-
2119
#define RHO_KEYTYPE "rho"
2220

2321
struct hop_params {
@@ -680,23 +678,35 @@ struct route_step *process_onionpacket(
680678
}
681679

682680
#if DEVELOPER
683-
unsigned dev_onion_reply_length = ONION_REPLY_SIZE;
684-
#define OUR_ONION_REPLY_SIZE dev_onion_reply_length
685-
#else
686-
#define OUR_ONION_REPLY_SIZE ONION_REPLY_SIZE
681+
unsigned dev_onion_reply_length = 256;
687682
#endif
688683

689684
struct onionreply *create_onionreply(const tal_t *ctx,
690685
const struct secret *shared_secret,
691686
const u8 *failure_msg)
692687
{
693688
size_t msglen = tal_count(failure_msg);
694-
size_t padlen = OUR_ONION_REPLY_SIZE - msglen;
689+
size_t padlen;
695690
struct onionreply *reply = tal(ctx, struct onionreply);
696691
u8 *payload = tal_arr(ctx, u8, 0);
697692
struct secret key;
698693
struct hmac hmac;
699694

695+
/* BOLT #4:
696+
* The _erring node_:
697+
* - SHOULD set `pad` such that the `failure_len` plus `pad_len`
698+
* is equal to 256.
699+
* - Note: this value is 118 bytes longer than the longest
700+
* currently-defined message.
701+
*/
702+
const u16 onion_reply_size = IFDEV(dev_onion_reply_length, 256);
703+
704+
/* We never do this currently, but could in future! */
705+
if (msglen > onion_reply_size)
706+
padlen = 0;
707+
else
708+
padlen = onion_reply_size - msglen;
709+
700710
/* BOLT #4:
701711
*
702712
* The node generating the error message (_erring node_) builds a return
@@ -715,15 +725,8 @@ struct onionreply *create_onionreply(const tal_t *ctx,
715725
towire_u16(&payload, padlen);
716726
towire_pad(&payload, padlen);
717727

718-
/* BOLT #4:
719-
*
720-
* The _erring node_:
721-
* - SHOULD set `pad` such that the `failure_len` plus `pad_len` is
722-
* equal to 256.
723-
* - Note: this value is 118 bytes longer than the longest
724-
* currently-defined message.
725-
*/
726-
assert(tal_count(payload) == OUR_ONION_REPLY_SIZE + 4);
728+
/* Two bytes for each length: failure_len and pad_len */
729+
assert(tal_count(payload) == onion_reply_size + 4);
727730

728731
/* BOLT #4:
729732
*
@@ -770,52 +773,47 @@ u8 *unwrap_onionreply(const tal_t *ctx,
770773
int *origin_index)
771774
{
772775
struct onionreply *r;
773-
struct secret key;
774-
struct hmac hmac;
775776
const u8 *cursor;
776-
u8 *final;
777777
size_t max;
778778
u16 msglen;
779779

780-
if (tal_count(reply->contents) != ONION_REPLY_SIZE + sizeof(hmac) + 4) {
781-
return NULL;
782-
}
783-
784780
r = new_onionreply(tmpctx, reply->contents);
785781
*origin_index = -1;
786782

787783
for (int i = 0; i < numhops; i++) {
784+
struct secret key;
785+
struct hmac hmac, expected_hmac;
786+
788787
/* Since the encryption is just XORing with the cipher
789788
* stream encryption is identical to decryption */
790789
r = wrap_onionreply(tmpctx, &shared_secrets[i], r);
791790

792791
/* Check if the HMAC matches, this means that this is
793792
* the origin */
794793
subkey_from_hmac("um", &shared_secrets[i], &key);
795-
compute_hmac(&key, r->contents + sizeof(hmac.bytes),
796-
tal_count(r->contents) - sizeof(hmac.bytes),
797-
NULL, 0, &hmac);
798-
if (memcmp(hmac.bytes, r->contents, sizeof(hmac.bytes)) == 0) {
794+
795+
cursor = r->contents;
796+
max = tal_count(r->contents);
797+
798+
fromwire_hmac(&cursor, &max, &hmac);
799+
/* Too short. */
800+
if (!cursor)
801+
return NULL;
802+
803+
compute_hmac(&key, cursor, max, NULL, 0, &expected_hmac);
804+
if (hmac_eq(&hmac, &expected_hmac)) {
799805
*origin_index = i;
800806
break;
801807
}
802808
}
809+
810+
/* Didn't find source, it's garbled */
803811
if (*origin_index == -1) {
804812
return NULL;
805813
}
806814

807-
cursor = r->contents + sizeof(hmac);
808-
max = tal_count(r->contents) - sizeof(hmac);
809815
msglen = fromwire_u16(&cursor, &max);
810-
811-
if (msglen > ONION_REPLY_SIZE) {
812-
return NULL;
813-
}
814-
815-
final = tal_arr(ctx, u8, msglen);
816-
if (!fromwire(&cursor, &max, final, msglen))
817-
return tal_free(final);
818-
return final;
816+
return fromwire_tal_arrn(ctx, &cursor, &max, msglen);
819817
}
820818

821819
struct onionpacket *sphinx_decompress(const tal_t *ctx,

tests/test_plugin.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1042,7 +1042,6 @@ def test_channel_state_change_history(node_factory, bitcoind):
10421042
assert(history[3]['message'] == "Closing complete")
10431043

10441044

1045-
@pytest.mark.xfail(strict=True)
10461045
@pytest.mark.developer("Gossip slow, and we test --dev-onion-reply-length")
10471046
def test_htlc_accepted_hook_fail(node_factory):
10481047
"""Send payments from l1 to l2, but l2 just declines everything.

wire/fromwire.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,8 @@ u8 *fromwire_tal_arrn(const tal_t *ctx,
223223

224224
arr = tal_arr(ctx, u8, num);
225225
fromwire_u8_array(cursor, max, arr, num);
226+
if (!*cursor)
227+
return tal_free(arr);
226228
return arr;
227229
}
228230

0 commit comments

Comments
 (0)