secp256k1_frost_sign(): use free_binding_factors() instead of manually rolled code #1331

pull muxator wants to merge 10 commits into bitcoin-core:master from bancaditalia:use-free_binding_factors-in-secp256k1_frost_sign changing 11 files +5193 −0
  1. muxator commented at 6:59 AM on May 30, 2023: none

    In this way we have a single way of clearing binding factors across the code base. Before this change, secp256k1_frost_sign() was the only function that rolled its own code.

  2. frost: first release of the secp256k1-frost implementation by Bank of Italy c31b9c193c
  3. doc: remove trailing newlines 53237240df
  4. frost: add copyright headers 42ca3cf661
  5. doc: add reference to the original authors and a link to the itcoin project c52279b8bc
  6. frost: reformat code base b4c4479e23
  7. frost: add secp256k1_frost_pubkey_save() and secp256k1_frost_pubkey_load() ddc7c41362
  8. frost: missing error check in deserialize_frost_signature() could lead to UB in secp256k1_frost_verify()
    The upstream function secp256k1_ge_set_xo_var() in src/group_impl.h returns an
    int signalling an error condition, but it is not marked with
    SECP256K1_WARN_UNUSED_RESULT.
    
    Thus, when compiling the Frost module, no warning was generated when
    deserialize_frost_signature() had no check covering the case that
    secp256k1_ge_set_xo_var() could fail.
    
    The GCC static analyzer found two potential execution paths in
    secp256k1_frost_verify() that would lead to undefined behaviour. For brevity,
    the issues are not reported here, but only in the Github PR associated with
    this commit (https://github.com/bancaditalia/secp256k1-frost/pull/5).
    
    As of today (2023-05-29), in bitcoin-core secp256k1, secp256k1_ge_set_xo_var()
    is still not marked SECP256K1_WARN_UNUSED_RESULT, see:
    https://github.com/bitcoin-core/secp256k1/blob/908e02d596b66203788e8945b1f9c93ff28a4536/src/group_impl.h#L280
    
    It may make sense to propose upstream to add that annotation.
    
    In order to replicate the issues fixed by this commit, compile with:
        ./configure SECP_CFLAGS="-fanalyzer -fanalyzer-transitivity" --disable-tests --disable-exhaustive-tests --disable-benchmark --enable-experimental --enable-module-frost
    18b40628c9
  9. frost: remove potential memory leak in secp256k1_frost_aggregate()
    The leak presented if compute_binding_factors() failed. In that case the error
    reporting path would not deallocate the binding factor that were allocated just
    above.
    
    Found with gcc 13.1 via:
        ./configure SECP_CFLAGS="-fanalyzer -fanalyzer-transitivity" --disable-tests --disable-exhaustive-tests --disable-benchmark --enable-experimental --enable-module-frost
    
    The analyzer found 3 leaks at main_impl.h:1403, all of them solved by this
    change. The branch analysis of the first leak was:
    
    ```
    In file included from src/secp256k1.c:767:
    src/modules/frost/main_impl.h: In function 'secp256k1_frost_aggregate':
    src/modules/frost/main_impl.h:1454:1: warning: leak of 'binding_factors.binding_factors' [CWE-401] [-Wanalyzer-malloc-leak]
     1454 | }
          | ^
      'secp256k1_frost_aggregate': events 1-2
        |
        | 1365 | SECP256K1_API int secp256k1_frost_aggregate(const secp256k1_context *ctx,
        |      |                   ^~~~~~~~~~~~~~~~~~~~~~~~~
        |      |                   |
        |      |                   (1) entry to 'secp256k1_frost_aggregate'
        [...]
        | 1394 |     binding_factors.binding_factors = (secp256k1_scalar *)
        | 1395 |             checked_malloc(&default_error_callback, num_signers * sizeof(secp256k1_scalar));
        |      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        |      |             |
        |      |             (10) calling 'checked_malloc' from 'secp256k1_frost_aggregate'
        |
        +--> 'checked_malloc': events 11-15
               |
               |src/util.h:118:31:
               |  118 | static SECP256K1_INLINE void *checked_malloc(const secp256k1_callback* cb, size_t size) {
               |      |                               ^~~~~~~~~~~~~~
               |      |                               |
               |      |                               (11) entry to 'checked_malloc'
               |  119 |     void *ret = malloc(size);
               |      |                 ~~~~~~~~~~~~
               |      |                 |
               |      |                 (12) allocated here
      [...]
      'secp256k1_frost_aggregate': events 29-30
        |
        | 1403 |     if (compute_binding_factors(&binding_factors, msg32, 32, num_signers, commitments) == 0) {
        |      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        |      |         |
        |      |         (29) ...to here
        |......
        | 1454 | }
        |      | ~
        |      | |
        |      | (30) 'binding_factors.binding_factors' leaks here; was allocated at (12)
        |
    ```
    49749cd0c2
  10. frost: move free_binding_factors() to the top
    In the next commit, this will allow us to call it from inside
    secp256k1_frost_sign().
    
    No functional changes.
    50a18bc2d3
  11. frost: use free_binding_factors() in secp256k1_frost_sign()
    In this way we have a single way of clearing binding factors across the code
    base. Before this change, secp256k1_frost_sign() was the only function that
    rolled its own code.
    7e2c60ce2a
  12. muxator commented at 6:59 AM on May 30, 2023: none

    sorry

  13. muxator closed this on May 30, 2023

  14. matteonardelli deleted the branch on Jun 5, 2023
Contributors

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin-core/secp256k1. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-27 04:15 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me