Skip to content

Commit 135ca0a

Browse files
committed
sp: mitigate worst-case scanning attack by removing found outputs from list
idea based on jonasnick's idea of tracking already found outputs in scanning [1], but without the need of dynamic memory allocation [1] jonasnick@311b4eb
1 parent c16252d commit 135ca0a

3 files changed

Lines changed: 12 additions & 6 deletions

File tree

examples/silentpayments.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ int main(void) {
365365
start = clock();
366366
ret = secp256k1_silentpayments_recipient_scan_outputs(ctx,
367367
found_output_ptrs, &n_found_outputs,
368-
(const secp256k1_xonly_pubkey * const *)tx_output_ptrs, N_OUTPUTS,
368+
(const secp256k1_xonly_pubkey**)tx_output_ptrs, N_OUTPUTS,
369369
bob_scan_key,
370370
&prevouts_summary,
371371
&unlabeled_spend_pubkey,
@@ -446,7 +446,7 @@ int main(void) {
446446
n_found_outputs = 0;
447447
ret = secp256k1_silentpayments_recipient_scan_outputs(ctx,
448448
found_output_ptrs, &n_found_outputs,
449-
(const secp256k1_xonly_pubkey * const *)tx_output_ptrs, 1, /* dummy scan with one output (we only care about Bob) */
449+
(const secp256k1_xonly_pubkey**)tx_output_ptrs, 1, /* dummy scan with one output (we only care about Bob) */
450450
carol_scan_key,
451451
&prevouts_summary,
452452
&unlabeled_spend_pubkey,

include/secp256k1_silentpayments.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipien
324324
const secp256k1_context *ctx,
325325
secp256k1_silentpayments_found_output **found_outputs,
326326
size_t *n_found_outputs,
327-
const secp256k1_xonly_pubkey * const *tx_outputs,
327+
const secp256k1_xonly_pubkey **tx_outputs,
328328
size_t n_tx_outputs,
329329
const unsigned char *scan_key32,
330330
const secp256k1_silentpayments_prevouts_summary *prevouts_summary,

src/modules/silentpayments/main_impl.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,7 @@ int secp256k1_silentpayments_recipient_prevouts_summary_create(
500500
int secp256k1_silentpayments_recipient_scan_outputs(
501501
const secp256k1_context *ctx,
502502
secp256k1_silentpayments_found_output **found_outputs, size_t *n_found_outputs,
503-
const secp256k1_xonly_pubkey * const *tx_outputs, size_t n_tx_outputs,
503+
const secp256k1_xonly_pubkey **tx_outputs, size_t n_tx_outputs,
504504
const unsigned char *scan_key32,
505505
const secp256k1_silentpayments_prevouts_summary *prevouts_summary,
506506
const secp256k1_pubkey *spend_pubkey,
@@ -512,7 +512,7 @@ int secp256k1_silentpayments_recipient_scan_outputs(
512512
secp256k1_xonly_pubkey output_xonly;
513513
unsigned char shared_secret[33];
514514
const unsigned char *label_tweak = NULL;
515-
size_t j, found_idx;
515+
size_t j, found_idx, n_remaining_tx_outputs;
516516
uint32_t k;
517517
int found, combined, valid_scan_key, ret;
518518

@@ -553,6 +553,7 @@ int secp256k1_silentpayments_recipient_scan_outputs(
553553
secp256k1_scalar_clear(&scan_key_scalar);
554554

555555
found_idx = 0;
556+
n_remaining_tx_outputs = n_tx_outputs;
556557
for (k = 0; k < n_tx_outputs; k++) {
557558
secp256k1_ge output_ge = spend_pubkey_ge;
558559
/* Calculate the output_tweak and convert it to a scalar.
@@ -577,7 +578,7 @@ int secp256k1_silentpayments_recipient_scan_outputs(
577578
}
578579
found = 0;
579580
secp256k1_xonly_pubkey_save(&output_xonly, &output_ge);
580-
for (j = 0; j < n_tx_outputs; j++) {
581+
for (j = 0; j < n_remaining_tx_outputs; j++) {
581582
if (secp256k1_xonly_pubkey_cmp(ctx, &output_xonly, tx_outputs[j]) == 0) {
582583
label_tweak = NULL;
583584
found = 1;
@@ -665,6 +666,11 @@ int secp256k1_silentpayments_recipient_scan_outputs(
665666
/* Set the label public key with an invalid public key value. */
666667
memset(&found_outputs[k]->label, 0, sizeof(secp256k1_pubkey));
667668
}
669+
/* Remove found entry from list of outputs to scan (shift remaining entries to the left) */
670+
for (j = found_idx + 1; j < n_remaining_tx_outputs; j++) {
671+
tx_outputs[j-1] = tx_outputs[j];
672+
}
673+
n_remaining_tx_outputs--;
668674
/* Reset everything for the next round of scanning. */
669675
label_tweak = NULL;
670676
/* BIP0352 specifies that k is serialized as a 4 byte (32 bit) value, so we check to make

0 commit comments

Comments
 (0)