csecp256k1

Haskell FFI bindings to bitcoin-core/secp256k1 (docs.ppad.tech/csecp256k1).
git clone git://git.ppad.tech/csecp256k1.git
Log | Files | Refs | README | LICENSE

main_impl.h (11753B)


      1 /***********************************************************************
      2  * Copyright (c) 2020 Jonas Nick                                       *
      3  * Distributed under the MIT software license, see the accompanying    *
      4  * file COPYING or https://www.opensource.org/licenses/mit-license.php.*
      5  ***********************************************************************/
      6 
      7 #ifndef SECP256K1_MODULE_EXTRAKEYS_MAIN_H
      8 #define SECP256K1_MODULE_EXTRAKEYS_MAIN_H
      9 
     10 #include "../../../include/secp256k1.h"
     11 #include "../../../include/secp256k1_extrakeys.h"
     12 #include "../../util.h"
     13 
     14 static SECP256K1_INLINE int haskellsecp256k1_v0_1_0_xonly_pubkey_load(const haskellsecp256k1_v0_1_0_context* ctx, haskellsecp256k1_v0_1_0_ge *ge, const haskellsecp256k1_v0_1_0_xonly_pubkey *pubkey) {
     15     return haskellsecp256k1_v0_1_0_pubkey_load(ctx, ge, (const haskellsecp256k1_v0_1_0_pubkey *) pubkey);
     16 }
     17 
     18 static SECP256K1_INLINE void haskellsecp256k1_v0_1_0_xonly_pubkey_save(haskellsecp256k1_v0_1_0_xonly_pubkey *pubkey, haskellsecp256k1_v0_1_0_ge *ge) {
     19     haskellsecp256k1_v0_1_0_pubkey_save((haskellsecp256k1_v0_1_0_pubkey *) pubkey, ge);
     20 }
     21 
     22 int haskellsecp256k1_v0_1_0_xonly_pubkey_parse(const haskellsecp256k1_v0_1_0_context* ctx, haskellsecp256k1_v0_1_0_xonly_pubkey *pubkey, const unsigned char *input32) {
     23     haskellsecp256k1_v0_1_0_ge pk;
     24     haskellsecp256k1_v0_1_0_fe x;
     25 
     26     VERIFY_CHECK(ctx != NULL);
     27     ARG_CHECK(pubkey != NULL);
     28     memset(pubkey, 0, sizeof(*pubkey));
     29     ARG_CHECK(input32 != NULL);
     30 
     31     if (!haskellsecp256k1_v0_1_0_fe_set_b32_limit(&x, input32)) {
     32         return 0;
     33     }
     34     if (!haskellsecp256k1_v0_1_0_ge_set_xo_var(&pk, &x, 0)) {
     35         return 0;
     36     }
     37     if (!haskellsecp256k1_v0_1_0_ge_is_in_correct_subgroup(&pk)) {
     38         return 0;
     39     }
     40     haskellsecp256k1_v0_1_0_xonly_pubkey_save(pubkey, &pk);
     41     return 1;
     42 }
     43 
     44 int haskellsecp256k1_v0_1_0_xonly_pubkey_serialize(const haskellsecp256k1_v0_1_0_context* ctx, unsigned char *output32, const haskellsecp256k1_v0_1_0_xonly_pubkey *pubkey) {
     45     haskellsecp256k1_v0_1_0_ge pk;
     46 
     47     VERIFY_CHECK(ctx != NULL);
     48     ARG_CHECK(output32 != NULL);
     49     memset(output32, 0, 32);
     50     ARG_CHECK(pubkey != NULL);
     51 
     52     if (!haskellsecp256k1_v0_1_0_xonly_pubkey_load(ctx, &pk, pubkey)) {
     53         return 0;
     54     }
     55     haskellsecp256k1_v0_1_0_fe_get_b32(output32, &pk.x);
     56     return 1;
     57 }
     58 
     59 int haskellsecp256k1_v0_1_0_xonly_pubkey_cmp(const haskellsecp256k1_v0_1_0_context* ctx, const haskellsecp256k1_v0_1_0_xonly_pubkey* pk0, const haskellsecp256k1_v0_1_0_xonly_pubkey* pk1) {
     60     unsigned char out[2][32];
     61     const haskellsecp256k1_v0_1_0_xonly_pubkey* pk[2];
     62     int i;
     63 
     64     VERIFY_CHECK(ctx != NULL);
     65     pk[0] = pk0; pk[1] = pk1;
     66     for (i = 0; i < 2; i++) {
     67         /* If the public key is NULL or invalid, xonly_pubkey_serialize will
     68          * call the illegal_callback and return 0. In that case we will
     69          * serialize the key as all zeros which is less than any valid public
     70          * key. This results in consistent comparisons even if NULL or invalid
     71          * pubkeys are involved and prevents edge cases such as sorting
     72          * algorithms that use this function and do not terminate as a
     73          * result. */
     74         if (!haskellsecp256k1_v0_1_0_xonly_pubkey_serialize(ctx, out[i], pk[i])) {
     75             /* Note that xonly_pubkey_serialize should already set the output to
     76              * zero in that case, but it's not guaranteed by the API, we can't
     77              * test it and writing a VERIFY_CHECK is more complex than
     78              * explicitly memsetting (again). */
     79             memset(out[i], 0, sizeof(out[i]));
     80         }
     81     }
     82     return haskellsecp256k1_v0_1_0_memcmp_var(out[0], out[1], sizeof(out[1]));
     83 }
     84 
     85 /** Keeps a group element as is if it has an even Y and otherwise negates it.
     86  *  y_parity is set to 0 in the former case and to 1 in the latter case.
     87  *  Requires that the coordinates of r are normalized. */
     88 static int haskellsecp256k1_v0_1_0_extrakeys_ge_even_y(haskellsecp256k1_v0_1_0_ge *r) {
     89     int y_parity = 0;
     90     VERIFY_CHECK(!haskellsecp256k1_v0_1_0_ge_is_infinity(r));
     91 
     92     if (haskellsecp256k1_v0_1_0_fe_is_odd(&r->y)) {
     93         haskellsecp256k1_v0_1_0_fe_negate(&r->y, &r->y, 1);
     94         y_parity = 1;
     95     }
     96     return y_parity;
     97 }
     98 
     99 int haskellsecp256k1_v0_1_0_xonly_pubkey_from_pubkey(const haskellsecp256k1_v0_1_0_context* ctx, haskellsecp256k1_v0_1_0_xonly_pubkey *xonly_pubkey, int *pk_parity, const haskellsecp256k1_v0_1_0_pubkey *pubkey) {
    100     haskellsecp256k1_v0_1_0_ge pk;
    101     int tmp;
    102 
    103     VERIFY_CHECK(ctx != NULL);
    104     ARG_CHECK(xonly_pubkey != NULL);
    105     ARG_CHECK(pubkey != NULL);
    106 
    107     if (!haskellsecp256k1_v0_1_0_pubkey_load(ctx, &pk, pubkey)) {
    108         return 0;
    109     }
    110     tmp = haskellsecp256k1_v0_1_0_extrakeys_ge_even_y(&pk);
    111     if (pk_parity != NULL) {
    112         *pk_parity = tmp;
    113     }
    114     haskellsecp256k1_v0_1_0_xonly_pubkey_save(xonly_pubkey, &pk);
    115     return 1;
    116 }
    117 
    118 int haskellsecp256k1_v0_1_0_xonly_pubkey_tweak_add(const haskellsecp256k1_v0_1_0_context* ctx, haskellsecp256k1_v0_1_0_pubkey *output_pubkey, const haskellsecp256k1_v0_1_0_xonly_pubkey *internal_pubkey, const unsigned char *tweak32) {
    119     haskellsecp256k1_v0_1_0_ge pk;
    120 
    121     VERIFY_CHECK(ctx != NULL);
    122     ARG_CHECK(output_pubkey != NULL);
    123     memset(output_pubkey, 0, sizeof(*output_pubkey));
    124     ARG_CHECK(internal_pubkey != NULL);
    125     ARG_CHECK(tweak32 != NULL);
    126 
    127     if (!haskellsecp256k1_v0_1_0_xonly_pubkey_load(ctx, &pk, internal_pubkey)
    128         || !haskellsecp256k1_v0_1_0_ec_pubkey_tweak_add_helper(&pk, tweak32)) {
    129         return 0;
    130     }
    131     haskellsecp256k1_v0_1_0_pubkey_save(output_pubkey, &pk);
    132     return 1;
    133 }
    134 
    135 int haskellsecp256k1_v0_1_0_xonly_pubkey_tweak_add_check(const haskellsecp256k1_v0_1_0_context* ctx, const unsigned char *tweaked_pubkey32, int tweaked_pk_parity, const haskellsecp256k1_v0_1_0_xonly_pubkey *internal_pubkey, const unsigned char *tweak32) {
    136     haskellsecp256k1_v0_1_0_ge pk;
    137     unsigned char pk_expected32[32];
    138 
    139     VERIFY_CHECK(ctx != NULL);
    140     ARG_CHECK(internal_pubkey != NULL);
    141     ARG_CHECK(tweaked_pubkey32 != NULL);
    142     ARG_CHECK(tweak32 != NULL);
    143 
    144     if (!haskellsecp256k1_v0_1_0_xonly_pubkey_load(ctx, &pk, internal_pubkey)
    145         || !haskellsecp256k1_v0_1_0_ec_pubkey_tweak_add_helper(&pk, tweak32)) {
    146         return 0;
    147     }
    148     haskellsecp256k1_v0_1_0_fe_normalize_var(&pk.x);
    149     haskellsecp256k1_v0_1_0_fe_normalize_var(&pk.y);
    150     haskellsecp256k1_v0_1_0_fe_get_b32(pk_expected32, &pk.x);
    151 
    152     return haskellsecp256k1_v0_1_0_memcmp_var(&pk_expected32, tweaked_pubkey32, 32) == 0
    153             && haskellsecp256k1_v0_1_0_fe_is_odd(&pk.y) == tweaked_pk_parity;
    154 }
    155 
    156 static void haskellsecp256k1_v0_1_0_keypair_save(haskellsecp256k1_v0_1_0_keypair *keypair, const haskellsecp256k1_v0_1_0_scalar *sk, haskellsecp256k1_v0_1_0_ge *pk) {
    157     haskellsecp256k1_v0_1_0_scalar_get_b32(&keypair->data[0], sk);
    158     haskellsecp256k1_v0_1_0_pubkey_save((haskellsecp256k1_v0_1_0_pubkey *)&keypair->data[32], pk);
    159 }
    160 
    161 
    162 static int haskellsecp256k1_v0_1_0_keypair_seckey_load(const haskellsecp256k1_v0_1_0_context* ctx, haskellsecp256k1_v0_1_0_scalar *sk, const haskellsecp256k1_v0_1_0_keypair *keypair) {
    163     int ret;
    164 
    165     ret = haskellsecp256k1_v0_1_0_scalar_set_b32_seckey(sk, &keypair->data[0]);
    166     /* We can declassify ret here because sk is only zero if a keypair function
    167      * failed (which zeroes the keypair) and its return value is ignored. */
    168     haskellsecp256k1_v0_1_0_declassify(ctx, &ret, sizeof(ret));
    169     ARG_CHECK(ret);
    170     return ret;
    171 }
    172 
    173 /* Load a keypair into pk and sk (if non-NULL). This function declassifies pk
    174  * and ARG_CHECKs that the keypair is not invalid. It always initializes sk and
    175  * pk with dummy values. */
    176 static int haskellsecp256k1_v0_1_0_keypair_load(const haskellsecp256k1_v0_1_0_context* ctx, haskellsecp256k1_v0_1_0_scalar *sk, haskellsecp256k1_v0_1_0_ge *pk, const haskellsecp256k1_v0_1_0_keypair *keypair) {
    177     int ret;
    178     const haskellsecp256k1_v0_1_0_pubkey *pubkey = (const haskellsecp256k1_v0_1_0_pubkey *)&keypair->data[32];
    179 
    180     /* Need to declassify the pubkey because pubkey_load ARG_CHECKs if it's
    181      * invalid. */
    182     haskellsecp256k1_v0_1_0_declassify(ctx, pubkey, sizeof(*pubkey));
    183     ret = haskellsecp256k1_v0_1_0_pubkey_load(ctx, pk, pubkey);
    184     if (sk != NULL) {
    185         ret = ret && haskellsecp256k1_v0_1_0_keypair_seckey_load(ctx, sk, keypair);
    186     }
    187     if (!ret) {
    188         *pk = haskellsecp256k1_v0_1_0_ge_const_g;
    189         if (sk != NULL) {
    190             *sk = haskellsecp256k1_v0_1_0_scalar_one;
    191         }
    192     }
    193     return ret;
    194 }
    195 
    196 int haskellsecp256k1_v0_1_0_keypair_create(const haskellsecp256k1_v0_1_0_context* ctx, haskellsecp256k1_v0_1_0_keypair *keypair, const unsigned char *seckey32) {
    197     haskellsecp256k1_v0_1_0_scalar sk;
    198     haskellsecp256k1_v0_1_0_ge pk;
    199     int ret = 0;
    200     VERIFY_CHECK(ctx != NULL);
    201     ARG_CHECK(keypair != NULL);
    202     memset(keypair, 0, sizeof(*keypair));
    203     ARG_CHECK(haskellsecp256k1_v0_1_0_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
    204     ARG_CHECK(seckey32 != NULL);
    205 
    206     ret = haskellsecp256k1_v0_1_0_ec_pubkey_create_helper(&ctx->ecmult_gen_ctx, &sk, &pk, seckey32);
    207     haskellsecp256k1_v0_1_0_keypair_save(keypair, &sk, &pk);
    208     haskellsecp256k1_v0_1_0_memczero(keypair, sizeof(*keypair), !ret);
    209 
    210     haskellsecp256k1_v0_1_0_scalar_clear(&sk);
    211     return ret;
    212 }
    213 
    214 int haskellsecp256k1_v0_1_0_keypair_sec(const haskellsecp256k1_v0_1_0_context* ctx, unsigned char *seckey, const haskellsecp256k1_v0_1_0_keypair *keypair) {
    215     VERIFY_CHECK(ctx != NULL);
    216     ARG_CHECK(seckey != NULL);
    217     memset(seckey, 0, 32);
    218     ARG_CHECK(keypair != NULL);
    219 
    220     memcpy(seckey, &keypair->data[0], 32);
    221     return 1;
    222 }
    223 
    224 int haskellsecp256k1_v0_1_0_keypair_pub(const haskellsecp256k1_v0_1_0_context* ctx, haskellsecp256k1_v0_1_0_pubkey *pubkey, const haskellsecp256k1_v0_1_0_keypair *keypair) {
    225     VERIFY_CHECK(ctx != NULL);
    226     ARG_CHECK(pubkey != NULL);
    227     memset(pubkey, 0, sizeof(*pubkey));
    228     ARG_CHECK(keypair != NULL);
    229 
    230     memcpy(pubkey->data, &keypair->data[32], sizeof(*pubkey));
    231     return 1;
    232 }
    233 
    234 int haskellsecp256k1_v0_1_0_keypair_xonly_pub(const haskellsecp256k1_v0_1_0_context* ctx, haskellsecp256k1_v0_1_0_xonly_pubkey *pubkey, int *pk_parity, const haskellsecp256k1_v0_1_0_keypair *keypair) {
    235     haskellsecp256k1_v0_1_0_ge pk;
    236     int tmp;
    237 
    238     VERIFY_CHECK(ctx != NULL);
    239     ARG_CHECK(pubkey != NULL);
    240     memset(pubkey, 0, sizeof(*pubkey));
    241     ARG_CHECK(keypair != NULL);
    242 
    243     if (!haskellsecp256k1_v0_1_0_keypair_load(ctx, NULL, &pk, keypair)) {
    244         return 0;
    245     }
    246     tmp = haskellsecp256k1_v0_1_0_extrakeys_ge_even_y(&pk);
    247     if (pk_parity != NULL) {
    248         *pk_parity = tmp;
    249     }
    250     haskellsecp256k1_v0_1_0_xonly_pubkey_save(pubkey, &pk);
    251 
    252     return 1;
    253 }
    254 
    255 int haskellsecp256k1_v0_1_0_keypair_xonly_tweak_add(const haskellsecp256k1_v0_1_0_context* ctx, haskellsecp256k1_v0_1_0_keypair *keypair, const unsigned char *tweak32) {
    256     haskellsecp256k1_v0_1_0_ge pk;
    257     haskellsecp256k1_v0_1_0_scalar sk;
    258     int y_parity;
    259     int ret;
    260 
    261     VERIFY_CHECK(ctx != NULL);
    262     ARG_CHECK(keypair != NULL);
    263     ARG_CHECK(tweak32 != NULL);
    264 
    265     ret = haskellsecp256k1_v0_1_0_keypair_load(ctx, &sk, &pk, keypair);
    266     memset(keypair, 0, sizeof(*keypair));
    267 
    268     y_parity = haskellsecp256k1_v0_1_0_extrakeys_ge_even_y(&pk);
    269     if (y_parity == 1) {
    270         haskellsecp256k1_v0_1_0_scalar_negate(&sk, &sk);
    271     }
    272 
    273     ret &= haskellsecp256k1_v0_1_0_ec_seckey_tweak_add_helper(&sk, tweak32);
    274     ret &= haskellsecp256k1_v0_1_0_ec_pubkey_tweak_add_helper(&pk, tweak32);
    275 
    276     haskellsecp256k1_v0_1_0_declassify(ctx, &ret, sizeof(ret));
    277     if (ret) {
    278         haskellsecp256k1_v0_1_0_keypair_save(keypair, &sk, &pk);
    279     }
    280 
    281     haskellsecp256k1_v0_1_0_scalar_clear(&sk);
    282     return ret;
    283 }
    284 
    285 #endif