diff --git a/common/bech32_util.c b/common/bech32_util.c index bae0f1e814dc..3003873351c5 100644 --- a/common/bech32_util.c +++ b/common/bech32_util.c @@ -31,7 +31,7 @@ static u8 get_u5_bit(const u5 *src, size_t bitoff) return ((src[bitoff / 5] >> (4 - (bitoff % 5))) & 1); } -void bech32_pull_bits(u8 **data, const u5 *src, size_t nbits) +bool bech32_pull_bits(u8 **data, const u5 *src, size_t nbits) { size_t i; size_t data_len = tal_count(*data); @@ -46,6 +46,27 @@ void bech32_pull_bits(u8 **data, const u5 *src, size_t nbits) } data_len++; } + + /* BIP-173: + * + * Decoding... + * - Any incomplete group at the end MUST be 4 bits or less, MUST be all zeroes, and is discarded + */ + size_t remaining_bits = nbits - i; + + if (remaining_bits > 0) { + if (remaining_bits > 4) { + return false; + } + + for (size_t b = 0; b < remaining_bits; b++) { + if (get_u5_bit(src, i + b) != 0) { + return false; + } + } + } + + return true; } /* Returns a char, tracks case. */ @@ -95,7 +116,9 @@ bool from_bech32_charset(const tal_t *ctx, goto fail; *data = tal_arr(ctx, u8, 0); - bech32_pull_bits(data, u5data, tal_bytelen(u5data) * 5); + if (!bech32_pull_bits(data, u5data, tal_bytelen(u5data) * 5)) { + goto fail; + } tal_free(u5data); return true; diff --git a/common/bech32_util.h b/common/bech32_util.h index f2857bde4935..bfc9b22e0059 100644 --- a/common/bech32_util.h +++ b/common/bech32_util.h @@ -13,7 +13,7 @@ void bech32_push_bits(u5 **data, const void *src, size_t nbits); /** * Push the bytes in src in 8 bit format onto the end of data. */ -void bech32_pull_bits(u8 **data, const u5 *src, size_t nbits); +bool bech32_pull_bits(u8 **data, const u5 *src, size_t nbits); /** * Checksumless bech32 routines. diff --git a/plugins/offers.c b/plugins/offers.c index 48ecff4f4fdb..cdfcb3c78fd2 100644 --- a/plugins/offers.c +++ b/plugins/offers.c @@ -477,7 +477,9 @@ static u8 *encrypted_decode(const tal_t *ctx, const char *str, char **fail) { goto fail; } u8 *data8bit = tal_arr(data, u8, 0); - bech32_pull_bits(&data8bit, data, datalen*5); + if (!bech32_pull_bits(&data8bit, data, datalen*5)) { + goto fail; + } return data8bit; fail: