9
9
#include <assert.h>
10
10
#include <string.h>
11
11
12
+ #if defined HAVE_CONFIG_H
13
+ #include "libsecp256k1-config.h"
14
+ #endif
15
+
16
+ #include "include/secp256k1_rangeproof.h"
17
+ #include "include/secp256k1_surjectionproof.h"
12
18
#include "modules/rangeproof/borromean.h"
13
19
#include "modules/surjection/surjection_impl.h"
14
20
#include "hash.h"
15
- #include "include/secp256k1_rangeproof.h"
16
- #include "include/secp256k1_surjectionproof.h"
21
+
22
+ #ifdef USE_REDUCED_SURJECTION_PROOF_SIZE
23
+ #undef SECP256K1_SURJECTIONPROOF_MAX_USED_INPUTS
24
+ #define SECP256K1_SURJECTIONPROOF_MAX_USED_INPUTS 16
25
+ #endif
17
26
18
27
static size_t secp256k1_count_bits_set (const unsigned char * data , size_t count ) {
19
28
size_t ret = 0 ;
@@ -35,6 +44,9 @@ static size_t secp256k1_count_bits_set(const unsigned char* data, size_t count)
35
44
return ret ;
36
45
}
37
46
47
+ #ifdef USE_REDUCED_SURJECTION_PROOF_SIZE
48
+ static
49
+ #endif
38
50
int secp256k1_surjectionproof_parse (const secp256k1_context * ctx , secp256k1_surjectionproof * proof , const unsigned char * input , size_t inputlen ) {
39
51
size_t n_inputs ;
40
52
size_t signature_len ;
@@ -55,6 +67,15 @@ int secp256k1_surjectionproof_parse(const secp256k1_context* ctx, secp256k1_surj
55
67
return 0 ;
56
68
}
57
69
70
+ /* Check that the bitvector of used inputs is of the claimed
71
+ * length; i.e. the final byte has no "padding bits" set */
72
+ if (n_inputs % 8 != 0 ) {
73
+ const unsigned char padding_mask = (~0U ) << (n_inputs % 8 );
74
+ if ((input [2 + (n_inputs + 7 ) / 8 - 1 ] & padding_mask ) != 0 ) {
75
+ return 0 ;
76
+ }
77
+ }
78
+
58
79
signature_len = 32 * (1 + secp256k1_count_bits_set (& input [2 ], (n_inputs + 7 ) / 8 ));
59
80
if (inputlen != 2 + (n_inputs + 7 ) / 8 + signature_len ) {
60
81
return 0 ;
@@ -151,6 +172,48 @@ static size_t secp256k1_surjectionproof_csprng_next(secp256k1_surjectionproof_cs
151
172
}
152
173
}
153
174
175
+ /* While '_allocate_initialized' may be a wordy suffix for this function, and '_create'
176
+ * may have been more appropriate, '_create' could be confused with '_generate',
177
+ * as the meanings for the words are close. Therefore, more wordy, but less
178
+ * ambiguous suffix was chosen. */
179
+ int secp256k1_surjectionproof_allocate_initialized (const secp256k1_context * ctx , secp256k1_surjectionproof * * proof_out_p , size_t * input_index , const secp256k1_fixed_asset_tag * fixed_input_tags , const size_t n_input_tags , const size_t n_input_tags_to_use , const secp256k1_fixed_asset_tag * fixed_output_tag , const size_t n_max_iterations , const unsigned char * random_seed32 ) {
180
+ int ret = 0 ;
181
+ secp256k1_surjectionproof * proof ;
182
+
183
+ VERIFY_CHECK (ctx != NULL );
184
+
185
+ ARG_CHECK (proof_out_p != NULL );
186
+ * proof_out_p = 0 ;
187
+
188
+ proof = (secp256k1_surjectionproof * )checked_malloc (& ctx -> error_callback , sizeof (secp256k1_surjectionproof ));
189
+ if (proof != NULL ) {
190
+ ret = secp256k1_surjectionproof_initialize (ctx , proof , input_index , fixed_input_tags , n_input_tags , n_input_tags_to_use , fixed_output_tag , n_max_iterations , random_seed32 );
191
+ if (ret ) {
192
+ * proof_out_p = proof ;
193
+ }
194
+ else {
195
+ free (proof );
196
+ }
197
+ }
198
+ return ret ;
199
+ }
200
+
201
+ /* secp256k1_surjectionproof structure may also be allocated on the stack,
202
+ * and initialized explicitly via secp256k1_surjectionproof_initialize().
203
+ * Supplying stack-allocated struct to _destroy() will result in calling
204
+ * free() with the pointer that points at the stack, with disasterous
205
+ * consequences. Thus, it is not advised to mix heap- and stack-allocating
206
+ * approaches to working with this struct. It is possible to detect this
207
+ * situation by using additional field in the struct that can be set to
208
+ * special value depending on the allocation path, and check it here.
209
+ * But currently, it is not seen as big enough concern to warrant this extra code .*/
210
+ void secp256k1_surjectionproof_destroy (secp256k1_surjectionproof * proof ) {
211
+ if (proof != NULL ) {
212
+ VERIFY_CHECK (proof -> n_inputs <= SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS );
213
+ free (proof );
214
+ }
215
+ }
216
+
154
217
int secp256k1_surjectionproof_initialize (const secp256k1_context * ctx , secp256k1_surjectionproof * proof , size_t * input_index , const secp256k1_fixed_asset_tag * fixed_input_tags , const size_t n_input_tags , const size_t n_input_tags_to_use , const secp256k1_fixed_asset_tag * fixed_output_tag , const size_t n_max_iterations , const unsigned char * random_seed32 ) {
155
218
secp256k1_surjectionproof_csprng csprng ;
156
219
size_t n_iterations = 0 ;
@@ -162,6 +225,7 @@ int secp256k1_surjectionproof_initialize(const secp256k1_context* ctx, secp256k1
162
225
ARG_CHECK (fixed_output_tag != NULL );
163
226
ARG_CHECK (random_seed32 != NULL );
164
227
ARG_CHECK (n_input_tags <= SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS );
228
+ ARG_CHECK (n_input_tags_to_use <= SECP256K1_SURJECTIONPROOF_MAX_USED_INPUTS );
165
229
ARG_CHECK (n_input_tags_to_use <= n_input_tags );
166
230
(void ) ctx ;
167
231
@@ -219,10 +283,8 @@ int secp256k1_surjectionproof_generate(const secp256k1_context* ctx, secp256k1_s
219
283
size_t n_total_pubkeys ;
220
284
size_t n_used_pubkeys ;
221
285
size_t ring_input_index = 0 ;
222
- secp256k1_gej ring_pubkeys [SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS ];
223
- secp256k1_scalar borromean_s [SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS ];
224
- secp256k1_ge inputs [SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS ];
225
- secp256k1_ge output ;
286
+ secp256k1_gej ring_pubkeys [SECP256K1_SURJECTIONPROOF_MAX_USED_INPUTS ];
287
+ secp256k1_scalar borromean_s [SECP256K1_SURJECTIONPROOF_MAX_USED_INPUTS ];
226
288
unsigned char msg32 [32 ];
227
289
228
290
VERIFY_CHECK (ctx != NULL );
@@ -261,17 +323,14 @@ int secp256k1_surjectionproof_generate(const secp256k1_context* ctx, secp256k1_s
261
323
return 0 ;
262
324
}
263
325
264
- secp256k1_generator_load (& output , ephemeral_output_tag );
265
- for (i = 0 ; i < n_total_pubkeys ; i ++ ) {
266
- secp256k1_generator_load (& inputs [i ], & ephemeral_input_tags [i ]);
326
+ if (secp256k1_surjection_compute_public_keys (ring_pubkeys , n_used_pubkeys , ephemeral_input_tags , n_total_pubkeys , proof -> used_inputs , ephemeral_output_tag , input_index , & ring_input_index ) == 0 ) {
327
+ return 0 ;
267
328
}
268
329
269
- secp256k1_surjection_compute_public_keys (ring_pubkeys , n_used_pubkeys , inputs , n_total_pubkeys , proof -> used_inputs , & output , input_index , & ring_input_index );
270
-
271
330
/* Produce signature */
272
331
rsizes [0 ] = (int ) n_used_pubkeys ;
273
332
indices [0 ] = (int ) ring_input_index ;
274
- secp256k1_surjection_genmessage (msg32 , inputs , n_total_pubkeys , & output );
333
+ secp256k1_surjection_genmessage (msg32 , ephemeral_input_tags , n_total_pubkeys , ephemeral_output_tag );
275
334
if (secp256k1_surjection_genrand (borromean_s , n_used_pubkeys , & blinding_key ) == 0 ) {
276
335
return 0 ;
277
336
}
@@ -289,15 +348,16 @@ int secp256k1_surjectionproof_generate(const secp256k1_context* ctx, secp256k1_s
289
348
return 1 ;
290
349
}
291
350
351
+ #ifdef USE_REDUCED_SURJECTION_PROOF_SIZE
352
+ static
353
+ #endif
292
354
int secp256k1_surjectionproof_verify (const secp256k1_context * ctx , const secp256k1_surjectionproof * proof , const secp256k1_generator * ephemeral_input_tags , size_t n_ephemeral_input_tags , const secp256k1_generator * ephemeral_output_tag ) {
293
355
size_t rsizes [1 ]; /* array needed for borromean sig API */
294
356
size_t i ;
295
357
size_t n_total_pubkeys ;
296
358
size_t n_used_pubkeys ;
297
- secp256k1_gej ring_pubkeys [SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS ];
298
- secp256k1_scalar borromean_s [SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS ];
299
- secp256k1_ge inputs [SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS ];
300
- secp256k1_ge output ;
359
+ secp256k1_gej ring_pubkeys [SECP256K1_SURJECTIONPROOF_MAX_USED_INPUTS ];
360
+ secp256k1_scalar borromean_s [SECP256K1_SURJECTIONPROOF_MAX_USED_INPUTS ];
301
361
unsigned char msg32 [32 ];
302
362
303
363
VERIFY_CHECK (ctx != NULL );
@@ -313,12 +373,12 @@ int secp256k1_surjectionproof_verify(const secp256k1_context* ctx, const secp256
313
373
return 0 ;
314
374
}
315
375
316
- secp256k1_generator_load ( & output , ephemeral_output_tag );
317
- for ( i = 0 ; i < n_total_pubkeys ; i ++ ) {
318
- secp256k1_generator_load ( & inputs [ i ], & ephemeral_input_tags [ i ]) ;
376
+ /* Reject proofs with too many used inputs in USE_REDUCED_SURJECTION_PROOF_SIZE mode */
377
+ if ( n_used_pubkeys > SECP256K1_SURJECTIONPROOF_MAX_USED_INPUTS ) {
378
+ return 0 ;
319
379
}
320
380
321
- if (secp256k1_surjection_compute_public_keys (ring_pubkeys , n_used_pubkeys , inputs , n_total_pubkeys , proof -> used_inputs , & output , 0 , NULL ) == 0 ) {
381
+ if (secp256k1_surjection_compute_public_keys (ring_pubkeys , n_used_pubkeys , ephemeral_input_tags , n_total_pubkeys , proof -> used_inputs , ephemeral_output_tag , 0 , NULL ) == 0 ) {
322
382
return 0 ;
323
383
}
324
384
@@ -331,7 +391,7 @@ int secp256k1_surjectionproof_verify(const secp256k1_context* ctx, const secp256
331
391
return 0 ;
332
392
}
333
393
}
334
- secp256k1_surjection_genmessage (msg32 , inputs , n_total_pubkeys , & output );
394
+ secp256k1_surjection_genmessage (msg32 , ephemeral_input_tags , n_total_pubkeys , ephemeral_output_tag );
335
395
return secp256k1_borromean_verify (& ctx -> ecmult_ctx , NULL , & proof -> data [0 ], borromean_s , ring_pubkeys , rsizes , 1 , msg32 , 32 );
336
396
}
337
397
0 commit comments