// Copyright (c) 2013 Pieter Wuille // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef _SECP256K1_FIELD_IMPL_H_ #define _SECP256K1_FIELD_IMPL_H_ #if defined(USE_FIELD_GMP) #include "field_gmp.h" #elif defined(USE_FIELD_10X26) #include "field_10x26.h" #elif defined(USE_FIELD_5X52) #include "field_5x52.h" #else #error "Please select field implementation" #endif void static secp256k1_fe_get_hex(char *r, int *rlen, const secp256k1_fe_t *a) { if (*rlen < 65) { *rlen = 65; return; } *rlen = 65; unsigned char tmp[32]; secp256k1_fe_t b = *a; secp256k1_fe_normalize(&b); secp256k1_fe_get_b32(tmp, &b); for (int i=0; i<32; i++) { static const char *c = "0123456789ABCDEF"; r[2*i] = c[(tmp[i] >> 4) & 0xF]; r[2*i+1] = c[(tmp[i]) & 0xF]; } r[64] = 0x00; } void static secp256k1_fe_set_hex(secp256k1_fe_t *r, const char *a, int alen) { unsigned char tmp[32] = {}; static const int cvt[256] = {0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, 0, 1, 2, 3, 4, 5, 6,7,8,9,0,0,0,0,0,0, 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0}; for (int i=0; i<32; i++) { if (alen > i*2) tmp[32 - alen/2 + i] = (cvt[(unsigned char)a[2*i]] << 4) + cvt[(unsigned char)a[2*i+1]]; } secp256k1_fe_set_b32(r, tmp); } void static secp256k1_fe_sqrt(secp256k1_fe_t *r, const secp256k1_fe_t *a) { // calculate a^p, with p={15,780,1022,1023} secp256k1_fe_t a2; secp256k1_fe_sqr(&a2, a); secp256k1_fe_t a3; secp256k1_fe_mul(&a3, &a2, a); secp256k1_fe_t a6; secp256k1_fe_sqr(&a6, &a3); secp256k1_fe_t a12; secp256k1_fe_sqr(&a12, &a6); secp256k1_fe_t a15; secp256k1_fe_mul(&a15, &a12, &a3); secp256k1_fe_t a30; secp256k1_fe_sqr(&a30, &a15); secp256k1_fe_t a60; secp256k1_fe_sqr(&a60, &a30); secp256k1_fe_t a120; secp256k1_fe_sqr(&a120, &a60); secp256k1_fe_t a240; secp256k1_fe_sqr(&a240, &a120); secp256k1_fe_t a255; secp256k1_fe_mul(&a255, &a240, &a15); secp256k1_fe_t a510; secp256k1_fe_sqr(&a510, &a255); secp256k1_fe_t a750; secp256k1_fe_mul(&a750, &a510, &a240); secp256k1_fe_t a780; secp256k1_fe_mul(&a780, &a750, &a30); secp256k1_fe_t a1020; secp256k1_fe_sqr(&a1020, &a510); secp256k1_fe_t a1022; secp256k1_fe_mul(&a1022, &a1020, &a2); secp256k1_fe_t a1023; secp256k1_fe_mul(&a1023, &a1022, a); secp256k1_fe_t x = a15; for (int i=0; i<21; i++) { for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x); secp256k1_fe_mul(&x, &x, &a1023); } for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x); secp256k1_fe_mul(&x, &x, &a1022); for (int i=0; i<2; i++) { for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x); secp256k1_fe_mul(&x, &x, &a1023); } for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x); secp256k1_fe_mul(r, &x, &a780); } void static secp256k1_fe_inv(secp256k1_fe_t *r, const secp256k1_fe_t *a) { // calculate a^p, with p={45,63,1019,1023} secp256k1_fe_t a2; secp256k1_fe_sqr(&a2, a); secp256k1_fe_t a3; secp256k1_fe_mul(&a3, &a2, a); secp256k1_fe_t a4; secp256k1_fe_sqr(&a4, &a2); secp256k1_fe_t a5; secp256k1_fe_mul(&a5, &a4, a); secp256k1_fe_t a10; secp256k1_fe_sqr(&a10, &a5); secp256k1_fe_t a11; secp256k1_fe_mul(&a11, &a10, a); secp256k1_fe_t a21; secp256k1_fe_mul(&a21, &a11, &a10); secp256k1_fe_t a42; secp256k1_fe_sqr(&a42, &a21); secp256k1_fe_t a45; secp256k1_fe_mul(&a45, &a42, &a3); secp256k1_fe_t a63; secp256k1_fe_mul(&a63, &a42, &a21); secp256k1_fe_t a126; secp256k1_fe_sqr(&a126, &a63); secp256k1_fe_t a252; secp256k1_fe_sqr(&a252, &a126); secp256k1_fe_t a504; secp256k1_fe_sqr(&a504, &a252); secp256k1_fe_t a1008; secp256k1_fe_sqr(&a1008, &a504); secp256k1_fe_t a1019; secp256k1_fe_mul(&a1019, &a1008, &a11); secp256k1_fe_t a1023; secp256k1_fe_mul(&a1023, &a1019, &a4); secp256k1_fe_t x = a63; for (int i=0; i<21; i++) { for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x); secp256k1_fe_mul(&x, &x, &a1023); } for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x); secp256k1_fe_mul(&x, &x, &a1019); for (int i=0; i<2; i++) { for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x); secp256k1_fe_mul(&x, &x, &a1023); } for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x); secp256k1_fe_mul(r, &x, &a45); } void static secp256k1_fe_inv_var(secp256k1_fe_t *r, const secp256k1_fe_t *a) { #if defined(USE_FIELD_INV_BUILTIN) secp256k1_fe_inv(r, a); #elif defined(USE_FIELD_INV_NUM) unsigned char b[32]; secp256k1_fe_t c = *a; secp256k1_fe_normalize(&c); secp256k1_fe_get_b32(b, &c); secp256k1_num_t n; secp256k1_num_init(&n); secp256k1_num_set_bin(&n, b, 32); secp256k1_num_mod_inverse(&n, &n, &secp256k1_fe_consts->p); secp256k1_num_get_bin(b, 32, &n); secp256k1_num_free(&n); secp256k1_fe_set_b32(r, b); #else #error "Please select field inverse implementation" #endif } void static secp256k1_fe_start(void) { static const unsigned char secp256k1_fe_consts_p[] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F }; if (secp256k1_fe_consts == NULL) { secp256k1_fe_inner_start(); secp256k1_fe_consts_t *ret = (secp256k1_fe_consts_t*)malloc(sizeof(secp256k1_fe_consts_t)); secp256k1_num_init(&ret->p); secp256k1_num_set_bin(&ret->p, secp256k1_fe_consts_p, sizeof(secp256k1_fe_consts_p)); secp256k1_fe_consts = ret; } } void static secp256k1_fe_stop(void) { if (secp256k1_fe_consts != NULL) { secp256k1_fe_consts_t *c = (secp256k1_fe_consts_t*)secp256k1_fe_consts; secp256k1_num_free(&c->p); free((void*)c); secp256k1_fe_consts = NULL; secp256k1_fe_inner_stop(); } } #endif