github.com/ethereum/go-ethereum@v1.16.1/crypto/secp256k1/libsecp256k1/src/modules/extrakeys/main_impl.h (about)

     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 secp256k1_xonly_pubkey_load(const secp256k1_context* ctx, secp256k1_ge *ge, const secp256k1_xonly_pubkey *pubkey) {
    15      return secp256k1_pubkey_load(ctx, ge, (const secp256k1_pubkey *) pubkey);
    16  }
    17  
    18  static SECP256K1_INLINE void secp256k1_xonly_pubkey_save(secp256k1_xonly_pubkey *pubkey, secp256k1_ge *ge) {
    19      secp256k1_pubkey_save((secp256k1_pubkey *) pubkey, ge);
    20  }
    21  
    22  int secp256k1_xonly_pubkey_parse(const secp256k1_context* ctx, secp256k1_xonly_pubkey *pubkey, const unsigned char *input32) {
    23      secp256k1_ge pk;
    24      secp256k1_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 (!secp256k1_fe_set_b32_limit(&x, input32)) {
    32          return 0;
    33      }
    34      if (!secp256k1_ge_set_xo_var(&pk, &x, 0)) {
    35          return 0;
    36      }
    37      if (!secp256k1_ge_is_in_correct_subgroup(&pk)) {
    38          return 0;
    39      }
    40      secp256k1_xonly_pubkey_save(pubkey, &pk);
    41      return 1;
    42  }
    43  
    44  int secp256k1_xonly_pubkey_serialize(const secp256k1_context* ctx, unsigned char *output32, const secp256k1_xonly_pubkey *pubkey) {
    45      secp256k1_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 (!secp256k1_xonly_pubkey_load(ctx, &pk, pubkey)) {
    53          return 0;
    54      }
    55      secp256k1_fe_get_b32(output32, &pk.x);
    56      return 1;
    57  }
    58  
    59  int secp256k1_xonly_pubkey_cmp(const secp256k1_context* ctx, const secp256k1_xonly_pubkey* pk0, const secp256k1_xonly_pubkey* pk1) {
    60      unsigned char out[2][32];
    61      const secp256k1_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 (!secp256k1_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 secp256k1_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 secp256k1_extrakeys_ge_even_y(secp256k1_ge *r) {
    89      int y_parity = 0;
    90      VERIFY_CHECK(!secp256k1_ge_is_infinity(r));
    91  
    92      if (secp256k1_fe_is_odd(&r->y)) {
    93          secp256k1_fe_negate(&r->y, &r->y, 1);
    94          y_parity = 1;
    95      }
    96      return y_parity;
    97  }
    98  
    99  int secp256k1_xonly_pubkey_from_pubkey(const secp256k1_context* ctx, secp256k1_xonly_pubkey *xonly_pubkey, int *pk_parity, const secp256k1_pubkey *pubkey) {
   100      secp256k1_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 (!secp256k1_pubkey_load(ctx, &pk, pubkey)) {
   108          return 0;
   109      }
   110      tmp = secp256k1_extrakeys_ge_even_y(&pk);
   111      if (pk_parity != NULL) {
   112          *pk_parity = tmp;
   113      }
   114      secp256k1_xonly_pubkey_save(xonly_pubkey, &pk);
   115      return 1;
   116  }
   117  
   118  int secp256k1_xonly_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, const secp256k1_xonly_pubkey *internal_pubkey, const unsigned char *tweak32) {
   119      secp256k1_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 (!secp256k1_xonly_pubkey_load(ctx, &pk, internal_pubkey)
   128          || !secp256k1_ec_pubkey_tweak_add_helper(&pk, tweak32)) {
   129          return 0;
   130      }
   131      secp256k1_pubkey_save(output_pubkey, &pk);
   132      return 1;
   133  }
   134  
   135  int secp256k1_xonly_pubkey_tweak_add_check(const secp256k1_context* ctx, const unsigned char *tweaked_pubkey32, int tweaked_pk_parity, const secp256k1_xonly_pubkey *internal_pubkey, const unsigned char *tweak32) {
   136      secp256k1_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 (!secp256k1_xonly_pubkey_load(ctx, &pk, internal_pubkey)
   145          || !secp256k1_ec_pubkey_tweak_add_helper(&pk, tweak32)) {
   146          return 0;
   147      }
   148      secp256k1_fe_normalize_var(&pk.x);
   149      secp256k1_fe_normalize_var(&pk.y);
   150      secp256k1_fe_get_b32(pk_expected32, &pk.x);
   151  
   152      return secp256k1_memcmp_var(&pk_expected32, tweaked_pubkey32, 32) == 0
   153              && secp256k1_fe_is_odd(&pk.y) == tweaked_pk_parity;
   154  }
   155  
   156  static void secp256k1_keypair_save(secp256k1_keypair *keypair, const secp256k1_scalar *sk, secp256k1_ge *pk) {
   157      secp256k1_scalar_get_b32(&keypair->data[0], sk);
   158      secp256k1_pubkey_save((secp256k1_pubkey *)&keypair->data[32], pk);
   159  }
   160  
   161  
   162  static int secp256k1_keypair_seckey_load(const secp256k1_context* ctx, secp256k1_scalar *sk, const secp256k1_keypair *keypair) {
   163      int ret;
   164  
   165      ret = secp256k1_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      secp256k1_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 secp256k1_keypair_load(const secp256k1_context* ctx, secp256k1_scalar *sk, secp256k1_ge *pk, const secp256k1_keypair *keypair) {
   177      int ret;
   178      const secp256k1_pubkey *pubkey = (const secp256k1_pubkey *)&keypair->data[32];
   179  
   180      /* Need to declassify the pubkey because pubkey_load ARG_CHECKs if it's
   181       * invalid. */
   182      secp256k1_declassify(ctx, pubkey, sizeof(*pubkey));
   183      ret = secp256k1_pubkey_load(ctx, pk, pubkey);
   184      if (sk != NULL) {
   185          ret = ret && secp256k1_keypair_seckey_load(ctx, sk, keypair);
   186      }
   187      if (!ret) {
   188          *pk = secp256k1_ge_const_g;
   189          if (sk != NULL) {
   190              *sk = secp256k1_scalar_one;
   191          }
   192      }
   193      return ret;
   194  }
   195  
   196  int secp256k1_keypair_create(const secp256k1_context* ctx, secp256k1_keypair *keypair, const unsigned char *seckey32) {
   197      secp256k1_scalar sk;
   198      secp256k1_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(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
   204      ARG_CHECK(seckey32 != NULL);
   205  
   206      ret = secp256k1_ec_pubkey_create_helper(&ctx->ecmult_gen_ctx, &sk, &pk, seckey32);
   207      secp256k1_keypair_save(keypair, &sk, &pk);
   208      secp256k1_memczero(keypair, sizeof(*keypair), !ret);
   209  
   210      secp256k1_scalar_clear(&sk);
   211      return ret;
   212  }
   213  
   214  int secp256k1_keypair_sec(const secp256k1_context* ctx, unsigned char *seckey, const secp256k1_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 secp256k1_keypair_pub(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const secp256k1_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 secp256k1_keypair_xonly_pub(const secp256k1_context* ctx, secp256k1_xonly_pubkey *pubkey, int *pk_parity, const secp256k1_keypair *keypair) {
   235      secp256k1_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 (!secp256k1_keypair_load(ctx, NULL, &pk, keypair)) {
   244          return 0;
   245      }
   246      tmp = secp256k1_extrakeys_ge_even_y(&pk);
   247      if (pk_parity != NULL) {
   248          *pk_parity = tmp;
   249      }
   250      secp256k1_xonly_pubkey_save(pubkey, &pk);
   251  
   252      return 1;
   253  }
   254  
   255  int secp256k1_keypair_xonly_tweak_add(const secp256k1_context* ctx, secp256k1_keypair *keypair, const unsigned char *tweak32) {
   256      secp256k1_ge pk;
   257      secp256k1_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 = secp256k1_keypair_load(ctx, &sk, &pk, keypair);
   266      memset(keypair, 0, sizeof(*keypair));
   267  
   268      y_parity = secp256k1_extrakeys_ge_even_y(&pk);
   269      if (y_parity == 1) {
   270          secp256k1_scalar_negate(&sk, &sk);
   271      }
   272  
   273      ret &= secp256k1_ec_seckey_tweak_add_helper(&sk, tweak32);
   274      ret &= secp256k1_ec_pubkey_tweak_add_helper(&pk, tweak32);
   275  
   276      secp256k1_declassify(ctx, &ret, sizeof(ret));
   277      if (ret) {
   278          secp256k1_keypair_save(keypair, &sk, &pk);
   279      }
   280  
   281      secp256k1_scalar_clear(&sk);
   282      return ret;
   283  }
   284  
   285  #endif