2014-11-15 15:28:10 +00:00
|
|
|
/**********************************************************************
|
2015-02-03 17:27:00 -08:00
|
|
|
* Copyright (c) 2013-2015 Pieter Wuille *
|
2014-11-15 15:28:10 +00:00
|
|
|
* Distributed under the MIT software license, see the accompanying *
|
|
|
|
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
|
|
|
**********************************************************************/
|
2013-05-09 15:24:32 +02:00
|
|
|
|
2014-11-12 12:05:42 -08:00
|
|
|
#define SECP256K1_BUILD (1)
|
|
|
|
|
2014-09-08 23:09:06 +02:00
|
|
|
#include "include/secp256k1.h"
|
|
|
|
|
2014-08-18 23:07:46 +02:00
|
|
|
#include "util.h"
|
2014-03-07 01:11:01 +01:00
|
|
|
#include "num_impl.h"
|
|
|
|
#include "field_impl.h"
|
2014-10-28 04:08:15 -07:00
|
|
|
#include "scalar_impl.h"
|
2014-03-07 01:11:01 +01:00
|
|
|
#include "group_impl.h"
|
|
|
|
#include "ecmult_impl.h"
|
2015-05-13 17:31:47 -05:00
|
|
|
#include "ecmult_const_impl.h"
|
2014-10-26 03:42:24 -07:00
|
|
|
#include "ecmult_gen_impl.h"
|
2014-03-07 01:11:01 +01:00
|
|
|
#include "ecdsa_impl.h"
|
2014-10-27 02:57:27 -07:00
|
|
|
#include "eckey_impl.h"
|
2014-12-13 17:02:30 +01:00
|
|
|
#include "hash_impl.h"
|
2013-03-31 06:34:15 +02:00
|
|
|
|
2015-07-18 16:29:10 -04:00
|
|
|
#define ARG_CHECK(cond) do { \
|
|
|
|
if (EXPECT(!(cond), 0)) { \
|
|
|
|
ctx->illegal_callback.fn(#cond, ctx->illegal_callback.data); \
|
|
|
|
return 0; \
|
|
|
|
} \
|
|
|
|
} while(0)
|
|
|
|
|
|
|
|
static void default_illegal_callback_fn(const char* str, void* data) {
|
|
|
|
(void)data;
|
|
|
|
fprintf(stderr, "[libsecp256k1] illegal argument: %s\n", str);
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
static const callback_t default_illegal_callback = {
|
|
|
|
default_illegal_callback_fn,
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static void default_error_callback_fn(const char* str, void* data) {
|
|
|
|
(void)data;
|
|
|
|
fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str);
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
static const callback_t default_error_callback = {
|
|
|
|
default_error_callback_fn,
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2015-02-03 17:27:00 -08:00
|
|
|
struct secp256k1_context_struct {
|
|
|
|
secp256k1_ecmult_context_t ecmult_ctx;
|
|
|
|
secp256k1_ecmult_gen_context_t ecmult_gen_ctx;
|
2015-07-18 16:29:10 -04:00
|
|
|
callback_t illegal_callback;
|
|
|
|
callback_t error_callback;
|
2015-02-03 17:27:00 -08:00
|
|
|
};
|
|
|
|
|
2015-09-01 01:40:38 +00:00
|
|
|
secp256k1_context_t* secp256k1_context_create(unsigned int flags) {
|
2015-07-18 16:29:10 -04:00
|
|
|
secp256k1_context_t* ret = (secp256k1_context_t*)checked_malloc(&default_error_callback, sizeof(secp256k1_context_t));
|
|
|
|
ret->illegal_callback = default_illegal_callback;
|
|
|
|
ret->error_callback = default_error_callback;
|
2015-02-03 17:27:00 -08:00
|
|
|
|
|
|
|
secp256k1_ecmult_context_init(&ret->ecmult_ctx);
|
|
|
|
secp256k1_ecmult_gen_context_init(&ret->ecmult_gen_ctx);
|
|
|
|
|
|
|
|
if (flags & SECP256K1_CONTEXT_SIGN) {
|
2015-07-18 16:29:10 -04:00
|
|
|
secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &ret->error_callback);
|
2014-09-08 23:09:06 +02:00
|
|
|
}
|
2015-02-03 17:27:00 -08:00
|
|
|
if (flags & SECP256K1_CONTEXT_VERIFY) {
|
2015-07-18 16:29:10 -04:00
|
|
|
secp256k1_ecmult_context_build(&ret->ecmult_ctx, &ret->error_callback);
|
2014-09-08 23:09:06 +02:00
|
|
|
}
|
2015-02-03 17:27:00 -08:00
|
|
|
|
|
|
|
return ret;
|
2013-03-31 06:34:15 +02:00
|
|
|
}
|
|
|
|
|
2015-04-11 14:06:54 -05:00
|
|
|
secp256k1_context_t* secp256k1_context_clone(const secp256k1_context_t* ctx) {
|
2015-07-18 16:29:10 -04:00
|
|
|
secp256k1_context_t* ret = (secp256k1_context_t*)checked_malloc(&ctx->error_callback, sizeof(secp256k1_context_t));
|
|
|
|
ret->illegal_callback = ctx->illegal_callback;
|
|
|
|
ret->error_callback = ctx->error_callback;
|
|
|
|
secp256k1_ecmult_context_clone(&ret->ecmult_ctx, &ctx->ecmult_ctx, &ctx->error_callback);
|
|
|
|
secp256k1_ecmult_gen_context_clone(&ret->ecmult_gen_ctx, &ctx->ecmult_gen_ctx, &ctx->error_callback);
|
2015-04-11 14:06:54 -05:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-02-03 17:27:00 -08:00
|
|
|
void secp256k1_context_destroy(secp256k1_context_t* ctx) {
|
|
|
|
secp256k1_ecmult_context_clear(&ctx->ecmult_ctx);
|
|
|
|
secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx);
|
|
|
|
|
|
|
|
free(ctx);
|
2013-03-31 06:34:15 +02:00
|
|
|
}
|
|
|
|
|
2015-07-18 16:29:10 -04:00
|
|
|
void secp256k1_context_set_illegal_callback(secp256k1_context_t* ctx, void (*fun)(const char* message, void* data), void* data) {
|
|
|
|
ctx->illegal_callback.fn = fun;
|
|
|
|
ctx->illegal_callback.data = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
void secp256k1_context_set_error_callback(secp256k1_context_t* ctx, void (*fun)(const char* message, void* data), void* data) {
|
|
|
|
ctx->error_callback.fn = fun;
|
|
|
|
ctx->error_callback.data = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int secp256k1_pubkey_load(const secp256k1_context_t* ctx, secp256k1_ge_t* ge, const secp256k1_pubkey_t* pubkey) {
|
2015-07-20 13:36:55 -04:00
|
|
|
if (sizeof(secp256k1_ge_storage_t) == 64) {
|
|
|
|
/* When the secp256k1_ge_storage_t type is exactly 64 byte, use its
|
|
|
|
* representation inside secp256k1_pubkey_t, as conversion is very fast.
|
|
|
|
* Note that secp256k1_pubkey_save must use the same representation. */
|
|
|
|
secp256k1_ge_storage_t s;
|
|
|
|
memcpy(&s, &pubkey->data[0], 64);
|
|
|
|
secp256k1_ge_from_storage(ge, &s);
|
|
|
|
} else {
|
|
|
|
/* Otherwise, fall back to 32-byte big endian for X and Y. */
|
|
|
|
secp256k1_fe_t x, y;
|
|
|
|
secp256k1_fe_set_b32(&x, pubkey->data);
|
|
|
|
secp256k1_fe_set_b32(&y, pubkey->data + 32);
|
|
|
|
secp256k1_ge_set_xy(ge, &x, &y);
|
|
|
|
}
|
2015-07-18 16:29:10 -04:00
|
|
|
ARG_CHECK(!secp256k1_fe_is_zero(&ge->x));
|
|
|
|
return 1;
|
2015-07-20 13:36:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void secp256k1_pubkey_save(secp256k1_pubkey_t* pubkey, secp256k1_ge_t* ge) {
|
|
|
|
if (sizeof(secp256k1_ge_storage_t) == 64) {
|
|
|
|
secp256k1_ge_storage_t s;
|
|
|
|
secp256k1_ge_to_storage(&s, ge);
|
|
|
|
memcpy(&pubkey->data[0], &s, 64);
|
|
|
|
} else {
|
|
|
|
VERIFY_CHECK(!secp256k1_ge_is_infinity(ge));
|
|
|
|
secp256k1_fe_normalize_var(&ge->x);
|
|
|
|
secp256k1_fe_normalize_var(&ge->y);
|
|
|
|
secp256k1_fe_get_b32(pubkey->data, &ge->x);
|
|
|
|
secp256k1_fe_get_b32(pubkey->data + 32, &ge->y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int secp256k1_ec_pubkey_parse(const secp256k1_context_t* ctx, secp256k1_pubkey_t* pubkey, const unsigned char *input, int inputlen) {
|
|
|
|
secp256k1_ge_t Q;
|
|
|
|
|
|
|
|
(void)ctx;
|
|
|
|
if (!secp256k1_eckey_pubkey_parse(&Q, input, inputlen)) {
|
|
|
|
memset(pubkey, 0, sizeof(*pubkey));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
secp256k1_pubkey_save(pubkey, &Q);
|
|
|
|
secp256k1_ge_clear(&Q);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int secp256k1_ec_pubkey_serialize(const secp256k1_context_t* ctx, unsigned char *output, int *outputlen, const secp256k1_pubkey_t* pubkey, int compressed) {
|
|
|
|
secp256k1_ge_t Q;
|
|
|
|
|
|
|
|
(void)ctx;
|
2015-07-18 16:29:10 -04:00
|
|
|
return (secp256k1_pubkey_load(ctx, &Q, pubkey) &&
|
|
|
|
secp256k1_eckey_pubkey_serialize(&Q, output, outputlen, compressed));
|
2015-07-20 13:36:55 -04:00
|
|
|
}
|
|
|
|
|
2015-08-27 03:09:23 +02:00
|
|
|
static void secp256k1_ecdsa_signature_load(const secp256k1_context_t* ctx, secp256k1_scalar_t* r, secp256k1_scalar_t* s, const secp256k1_ecdsa_signature_t* sig) {
|
|
|
|
(void)ctx;
|
|
|
|
if (sizeof(secp256k1_scalar_t) == 32) {
|
|
|
|
/* When the secp256k1_scalar_t type is exactly 32 byte, use its
|
|
|
|
* representation inside secp256k1_ecdsa_signature_t, as conversion is very fast.
|
|
|
|
* Note that secp256k1_ecdsa_signature_save must use the same representation. */
|
|
|
|
memcpy(r, &sig->data[0], 32);
|
|
|
|
memcpy(s, &sig->data[32], 32);
|
|
|
|
} else {
|
|
|
|
secp256k1_scalar_set_b32(r, &sig->data[0], NULL);
|
|
|
|
secp256k1_scalar_set_b32(s, &sig->data[32], NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void secp256k1_ecdsa_signature_save(secp256k1_ecdsa_signature_t* sig, const secp256k1_scalar_t* r, const secp256k1_scalar_t* s) {
|
|
|
|
if (sizeof(secp256k1_scalar_t) == 32) {
|
|
|
|
memcpy(&sig->data[0], r, 32);
|
|
|
|
memcpy(&sig->data[32], s, 32);
|
|
|
|
} else {
|
|
|
|
secp256k1_scalar_get_b32(&sig->data[0], r);
|
|
|
|
secp256k1_scalar_get_b32(&sig->data[32], s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-26 16:00:55 +02:00
|
|
|
int secp256k1_ecdsa_signature_parse_der(const secp256k1_context_t* ctx, secp256k1_ecdsa_signature_t* sig, const unsigned char *input, int inputlen) {
|
2015-07-26 16:51:58 +02:00
|
|
|
secp256k1_scalar_t r, s;
|
2015-07-26 16:00:55 +02:00
|
|
|
|
|
|
|
(void)ctx;
|
2015-07-18 16:29:10 -04:00
|
|
|
ARG_CHECK(sig != NULL);
|
|
|
|
ARG_CHECK(input != NULL);
|
2015-07-26 16:00:55 +02:00
|
|
|
|
2015-07-26 16:51:58 +02:00
|
|
|
if (secp256k1_ecdsa_sig_parse(&r, &s, input, inputlen)) {
|
2015-08-27 03:09:23 +02:00
|
|
|
secp256k1_ecdsa_signature_save(sig, &r, &s);
|
2015-07-26 16:00:55 +02:00
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
memset(sig, 0, sizeof(*sig));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int secp256k1_ecdsa_signature_serialize_der(const secp256k1_context_t* ctx, unsigned char *output, int *outputlen, const secp256k1_ecdsa_signature_t* sig) {
|
2015-07-26 16:51:58 +02:00
|
|
|
secp256k1_scalar_t r, s;
|
2015-07-26 16:00:55 +02:00
|
|
|
|
|
|
|
(void)ctx;
|
2015-07-18 16:29:10 -04:00
|
|
|
ARG_CHECK(output != NULL);
|
|
|
|
ARG_CHECK(outputlen != NULL);
|
|
|
|
ARG_CHECK(sig != NULL);
|
2015-07-26 16:00:55 +02:00
|
|
|
|
2015-08-27 03:09:23 +02:00
|
|
|
secp256k1_ecdsa_signature_load(ctx, &r, &s, sig);
|
2015-07-26 16:51:58 +02:00
|
|
|
return secp256k1_ecdsa_sig_serialize(output, outputlen, &r, &s);
|
2015-07-26 16:00:55 +02:00
|
|
|
}
|
|
|
|
|
2015-08-28 01:50:47 +02:00
|
|
|
int secp256k1_ecdsa_verify(const secp256k1_context_t* ctx, const secp256k1_ecdsa_signature_t *sig, const unsigned char *msg32, const secp256k1_pubkey_t *pubkey) {
|
2015-01-25 17:32:08 +00:00
|
|
|
secp256k1_ge_t q;
|
2015-07-26 16:51:58 +02:00
|
|
|
secp256k1_scalar_t r, s;
|
2015-01-25 17:32:08 +00:00
|
|
|
secp256k1_scalar_t m;
|
2015-09-01 14:22:32 -04:00
|
|
|
VERIFY_CHECK(ctx != NULL);
|
2015-07-18 16:29:10 -04:00
|
|
|
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
|
|
|
|
ARG_CHECK(msg32 != NULL);
|
|
|
|
ARG_CHECK(sig != NULL);
|
|
|
|
ARG_CHECK(pubkey != NULL);
|
2014-08-18 23:07:46 +02:00
|
|
|
|
2014-11-26 17:26:39 +01:00
|
|
|
secp256k1_scalar_set_b32(&m, msg32, NULL);
|
2015-08-27 03:09:23 +02:00
|
|
|
secp256k1_ecdsa_signature_load(ctx, &r, &s, sig);
|
2015-07-18 16:29:10 -04:00
|
|
|
return (secp256k1_pubkey_load(ctx, &q, pubkey) &&
|
|
|
|
secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &r, &s, &q, &m));
|
2013-03-16 15:51:55 +01:00
|
|
|
}
|
|
|
|
|
2015-08-28 01:50:47 +02:00
|
|
|
static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, const void *data, unsigned int counter) {
|
2015-07-24 15:44:49 +02:00
|
|
|
unsigned char keydata[112];
|
|
|
|
int keylen = 64;
|
2014-12-13 18:06:33 +01:00
|
|
|
secp256k1_rfc6979_hmac_sha256_t rng;
|
2015-01-25 17:32:08 +00:00
|
|
|
unsigned int i;
|
2015-07-08 18:10:25 -04:00
|
|
|
/* We feed a byte array to the PRNG as input, consisting of:
|
|
|
|
* - the private key (32 bytes) and message (32 bytes), see RFC 6979 3.2d.
|
|
|
|
* - optionally 32 extra bytes of data, see RFC 6979 3.6 Additional Data.
|
2015-07-24 15:44:49 +02:00
|
|
|
* - optionally 16 extra bytes with the algorithm name (the extra data bytes
|
|
|
|
* are set to zeroes when not present, while the algorithm name is).
|
2015-07-08 18:10:25 -04:00
|
|
|
*/
|
|
|
|
memcpy(keydata, key32, 32);
|
|
|
|
memcpy(keydata + 32, msg32, 32);
|
|
|
|
if (data != NULL) {
|
|
|
|
memcpy(keydata + 64, data, 32);
|
2015-07-24 15:44:49 +02:00
|
|
|
keylen = 96;
|
2015-07-08 18:10:25 -04:00
|
|
|
}
|
2015-07-24 15:44:49 +02:00
|
|
|
if (algo16 != NULL) {
|
|
|
|
memset(keydata + keylen, 0, 96 - keylen);
|
|
|
|
memcpy(keydata + 96, algo16, 16);
|
|
|
|
keylen = 112;
|
|
|
|
}
|
|
|
|
secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, keylen);
|
2015-07-08 18:10:25 -04:00
|
|
|
memset(keydata, 0, sizeof(keydata));
|
2015-01-25 17:32:08 +00:00
|
|
|
for (i = 0; i <= counter; i++) {
|
2014-12-13 18:06:33 +01:00
|
|
|
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
|
|
|
|
}
|
|
|
|
secp256k1_rfc6979_hmac_sha256_finalize(&rng);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
const secp256k1_nonce_function_t secp256k1_nonce_function_rfc6979 = nonce_function_rfc6979;
|
|
|
|
const secp256k1_nonce_function_t secp256k1_nonce_function_default = nonce_function_rfc6979;
|
|
|
|
|
2015-08-28 01:50:47 +02:00
|
|
|
int secp256k1_ecdsa_sign(const secp256k1_context_t* ctx, secp256k1_ecdsa_signature_t *signature, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function_t noncefp, const void* noncedata) {
|
2015-08-27 03:09:23 +02:00
|
|
|
secp256k1_scalar_t r, s;
|
|
|
|
secp256k1_scalar_t sec, non, msg;
|
|
|
|
int ret = 0;
|
|
|
|
int overflow = 0;
|
|
|
|
unsigned int count = 0;
|
2015-09-01 14:22:32 -04:00
|
|
|
VERIFY_CHECK(ctx != NULL);
|
2015-08-27 03:09:23 +02:00
|
|
|
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
|
|
|
ARG_CHECK(msg32 != NULL);
|
|
|
|
ARG_CHECK(signature != NULL);
|
|
|
|
ARG_CHECK(seckey != NULL);
|
|
|
|
if (noncefp == NULL) {
|
|
|
|
noncefp = secp256k1_nonce_function_default;
|
|
|
|
}
|
|
|
|
|
|
|
|
secp256k1_scalar_set_b32(&sec, seckey, &overflow);
|
|
|
|
/* Fail if the secret key is invalid. */
|
|
|
|
if (!overflow && !secp256k1_scalar_is_zero(&sec)) {
|
|
|
|
secp256k1_scalar_set_b32(&msg, msg32, NULL);
|
|
|
|
while (1) {
|
|
|
|
unsigned char nonce32[32];
|
2015-08-28 01:50:47 +02:00
|
|
|
ret = noncefp(nonce32, msg32, seckey, NULL, noncedata, count);
|
2015-08-27 03:09:23 +02:00
|
|
|
if (!ret) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
secp256k1_scalar_set_b32(&non, nonce32, &overflow);
|
|
|
|
memset(nonce32, 0, 32);
|
|
|
|
if (!secp256k1_scalar_is_zero(&non) && !overflow) {
|
|
|
|
if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, NULL)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
secp256k1_scalar_clear(&msg);
|
|
|
|
secp256k1_scalar_clear(&non);
|
|
|
|
secp256k1_scalar_clear(&sec);
|
|
|
|
}
|
|
|
|
if (ret) {
|
|
|
|
secp256k1_ecdsa_signature_save(signature, &r, &s);
|
|
|
|
} else {
|
|
|
|
memset(signature, 0, sizeof(*signature));
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-02-03 17:27:00 -08:00
|
|
|
int secp256k1_ec_seckey_verify(const secp256k1_context_t* ctx, const unsigned char *seckey) {
|
2014-10-28 04:08:15 -07:00
|
|
|
secp256k1_scalar_t sec;
|
2015-01-25 17:32:08 +00:00
|
|
|
int ret;
|
2014-10-28 04:08:15 -07:00
|
|
|
int overflow;
|
2015-09-01 14:22:32 -04:00
|
|
|
VERIFY_CHECK(ctx != NULL);
|
2015-07-18 16:29:10 -04:00
|
|
|
ARG_CHECK(seckey != NULL);
|
2015-02-03 17:27:00 -08:00
|
|
|
(void)ctx;
|
2015-01-25 17:32:08 +00:00
|
|
|
|
2014-10-29 00:35:09 -07:00
|
|
|
secp256k1_scalar_set_b32(&sec, seckey, &overflow);
|
2015-01-25 17:32:08 +00:00
|
|
|
ret = !secp256k1_scalar_is_zero(&sec) && !overflow;
|
2014-10-28 04:08:15 -07:00
|
|
|
secp256k1_scalar_clear(&sec);
|
2013-05-05 00:49:30 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-07-20 13:36:55 -04:00
|
|
|
int secp256k1_ec_pubkey_create(const secp256k1_context_t* ctx, secp256k1_pubkey_t *pubkey, const unsigned char *seckey) {
|
2015-01-25 17:32:08 +00:00
|
|
|
secp256k1_gej_t pj;
|
|
|
|
secp256k1_ge_t p;
|
|
|
|
secp256k1_scalar_t sec;
|
2015-02-17 00:10:12 -08:00
|
|
|
int overflow;
|
Eliminate multiple-returns from secp256k1.c.
Goto, multiple returns, continue, and/or multiple breaks in a
loop are often used to build complex or non-local control
flow in software.
(They're all basically the same thing, and anyone axiomatically
opposing goto and not the rest is probably cargo-culting from
the title of Dijkstra's essay without thinking hard about it.)
Personally, I think the current use of these constructs in the
code base is fine: no where are we using them to create control-
flow that couldn't easily be described in plain English, which
is hard to read or reason about, or which looks like a trap for
future developers.
Some, however, prefer a more rules based approach to software
quality. In particular, MISRA forbids all of these constructs,
and for good experience based reasons. Rules also have the
benefit of being machine checkable and surviving individual
developers.
(To be fair-- MISRA also has a process for accommodating code that
breaks the rules for good reason).
I think that in general we should also try to satisfy the rules-
based measures of software quality, except where there is an
objective reason not do: a measurable performance difference,
logic that turns to spaghetti, etc.
Changing out all the multiple returns in secp256k1.c appears to
be basically neutral: Some parts become slightly less clear,
some parts slightly more.
2015-02-17 01:01:48 -08:00
|
|
|
int ret = 0;
|
2015-09-01 14:22:32 -04:00
|
|
|
VERIFY_CHECK(ctx != NULL);
|
2015-07-18 16:29:10 -04:00
|
|
|
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
|
|
|
ARG_CHECK(pubkey != NULL);
|
|
|
|
ARG_CHECK(seckey != NULL);
|
2014-08-18 23:07:46 +02:00
|
|
|
|
2015-02-17 00:10:12 -08:00
|
|
|
secp256k1_scalar_set_b32(&sec, seckey, &overflow);
|
2015-07-20 13:36:55 -04:00
|
|
|
ret = !overflow & !secp256k1_scalar_is_zero(&sec);
|
|
|
|
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec);
|
|
|
|
secp256k1_ge_set_gej(&p, &pj);
|
|
|
|
secp256k1_pubkey_save(pubkey, &p);
|
|
|
|
secp256k1_scalar_clear(&sec);
|
Eliminate multiple-returns from secp256k1.c.
Goto, multiple returns, continue, and/or multiple breaks in a
loop are often used to build complex or non-local control
flow in software.
(They're all basically the same thing, and anyone axiomatically
opposing goto and not the rest is probably cargo-culting from
the title of Dijkstra's essay without thinking hard about it.)
Personally, I think the current use of these constructs in the
code base is fine: no where are we using them to create control-
flow that couldn't easily be described in plain English, which
is hard to read or reason about, or which looks like a trap for
future developers.
Some, however, prefer a more rules based approach to software
quality. In particular, MISRA forbids all of these constructs,
and for good experience based reasons. Rules also have the
benefit of being machine checkable and surviving individual
developers.
(To be fair-- MISRA also has a process for accommodating code that
breaks the rules for good reason).
I think that in general we should also try to satisfy the rules-
based measures of software quality, except where there is an
objective reason not do: a measurable performance difference,
logic that turns to spaghetti, etc.
Changing out all the multiple returns in secp256k1.c appears to
be basically neutral: Some parts become slightly less clear,
some parts slightly more.
2015-02-17 01:01:48 -08:00
|
|
|
if (!ret) {
|
2015-07-20 13:36:55 -04:00
|
|
|
memset(pubkey, 0, sizeof(*pubkey));
|
2015-07-13 13:09:00 +01:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-02-03 17:27:00 -08:00
|
|
|
int secp256k1_ec_privkey_tweak_add(const secp256k1_context_t* ctx, unsigned char *seckey, const unsigned char *tweak) {
|
2015-01-25 17:32:08 +00:00
|
|
|
secp256k1_scalar_t term;
|
|
|
|
secp256k1_scalar_t sec;
|
Eliminate multiple-returns from secp256k1.c.
Goto, multiple returns, continue, and/or multiple breaks in a
loop are often used to build complex or non-local control
flow in software.
(They're all basically the same thing, and anyone axiomatically
opposing goto and not the rest is probably cargo-culting from
the title of Dijkstra's essay without thinking hard about it.)
Personally, I think the current use of these constructs in the
code base is fine: no where are we using them to create control-
flow that couldn't easily be described in plain English, which
is hard to read or reason about, or which looks like a trap for
future developers.
Some, however, prefer a more rules based approach to software
quality. In particular, MISRA forbids all of these constructs,
and for good experience based reasons. Rules also have the
benefit of being machine checkable and surviving individual
developers.
(To be fair-- MISRA also has a process for accommodating code that
breaks the rules for good reason).
I think that in general we should also try to satisfy the rules-
based measures of software quality, except where there is an
objective reason not do: a measurable performance difference,
logic that turns to spaghetti, etc.
Changing out all the multiple returns in secp256k1.c appears to
be basically neutral: Some parts become slightly less clear,
some parts slightly more.
2015-02-17 01:01:48 -08:00
|
|
|
int ret = 0;
|
2015-01-25 17:32:08 +00:00
|
|
|
int overflow = 0;
|
2015-09-01 14:22:32 -04:00
|
|
|
VERIFY_CHECK(ctx != NULL);
|
2015-07-18 16:29:10 -04:00
|
|
|
ARG_CHECK(seckey != NULL);
|
|
|
|
ARG_CHECK(tweak != NULL);
|
2015-02-03 17:27:00 -08:00
|
|
|
(void)ctx;
|
2014-08-18 23:07:46 +02:00
|
|
|
|
2014-10-29 00:35:09 -07:00
|
|
|
secp256k1_scalar_set_b32(&term, tweak, &overflow);
|
|
|
|
secp256k1_scalar_set_b32(&sec, seckey, NULL);
|
2014-10-27 03:27:55 -07:00
|
|
|
|
2015-01-25 17:32:08 +00:00
|
|
|
ret = secp256k1_eckey_privkey_tweak_add(&sec, &term) && !overflow;
|
2013-05-27 01:18:48 +02:00
|
|
|
if (ret) {
|
2014-10-29 00:35:09 -07:00
|
|
|
secp256k1_scalar_get_b32(seckey, &sec);
|
2014-10-27 03:27:55 -07:00
|
|
|
}
|
|
|
|
|
2014-10-28 04:08:15 -07:00
|
|
|
secp256k1_scalar_clear(&sec);
|
|
|
|
secp256k1_scalar_clear(&term);
|
2013-05-27 01:18:48 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-07-20 13:36:55 -04:00
|
|
|
int secp256k1_ec_pubkey_tweak_add(const secp256k1_context_t* ctx, secp256k1_pubkey_t *pubkey, const unsigned char *tweak) {
|
2015-01-25 17:32:08 +00:00
|
|
|
secp256k1_ge_t p;
|
|
|
|
secp256k1_scalar_t term;
|
Eliminate multiple-returns from secp256k1.c.
Goto, multiple returns, continue, and/or multiple breaks in a
loop are often used to build complex or non-local control
flow in software.
(They're all basically the same thing, and anyone axiomatically
opposing goto and not the rest is probably cargo-culting from
the title of Dijkstra's essay without thinking hard about it.)
Personally, I think the current use of these constructs in the
code base is fine: no where are we using them to create control-
flow that couldn't easily be described in plain English, which
is hard to read or reason about, or which looks like a trap for
future developers.
Some, however, prefer a more rules based approach to software
quality. In particular, MISRA forbids all of these constructs,
and for good experience based reasons. Rules also have the
benefit of being machine checkable and surviving individual
developers.
(To be fair-- MISRA also has a process for accommodating code that
breaks the rules for good reason).
I think that in general we should also try to satisfy the rules-
based measures of software quality, except where there is an
objective reason not do: a measurable performance difference,
logic that turns to spaghetti, etc.
Changing out all the multiple returns in secp256k1.c appears to
be basically neutral: Some parts become slightly less clear,
some parts slightly more.
2015-02-17 01:01:48 -08:00
|
|
|
int ret = 0;
|
2015-01-25 17:32:08 +00:00
|
|
|
int overflow = 0;
|
2015-09-01 14:22:32 -04:00
|
|
|
VERIFY_CHECK(ctx != NULL);
|
2015-07-18 16:29:10 -04:00
|
|
|
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
|
|
|
|
ARG_CHECK(pubkey != NULL);
|
|
|
|
ARG_CHECK(tweak != NULL);
|
2014-08-18 23:07:46 +02:00
|
|
|
|
2014-11-26 17:26:39 +01:00
|
|
|
secp256k1_scalar_set_b32(&term, tweak, &overflow);
|
2015-07-18 16:29:10 -04:00
|
|
|
if (!overflow && secp256k1_pubkey_load(ctx, &p, pubkey)) {
|
2015-07-20 13:36:55 -04:00
|
|
|
ret = secp256k1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &p, &term);
|
Eliminate multiple-returns from secp256k1.c.
Goto, multiple returns, continue, and/or multiple breaks in a
loop are often used to build complex or non-local control
flow in software.
(They're all basically the same thing, and anyone axiomatically
opposing goto and not the rest is probably cargo-culting from
the title of Dijkstra's essay without thinking hard about it.)
Personally, I think the current use of these constructs in the
code base is fine: no where are we using them to create control-
flow that couldn't easily be described in plain English, which
is hard to read or reason about, or which looks like a trap for
future developers.
Some, however, prefer a more rules based approach to software
quality. In particular, MISRA forbids all of these constructs,
and for good experience based reasons. Rules also have the
benefit of being machine checkable and surviving individual
developers.
(To be fair-- MISRA also has a process for accommodating code that
breaks the rules for good reason).
I think that in general we should also try to satisfy the rules-
based measures of software quality, except where there is an
objective reason not do: a measurable performance difference,
logic that turns to spaghetti, etc.
Changing out all the multiple returns in secp256k1.c appears to
be basically neutral: Some parts become slightly less clear,
some parts slightly more.
2015-02-17 01:01:48 -08:00
|
|
|
if (ret) {
|
2015-07-20 13:36:55 -04:00
|
|
|
secp256k1_pubkey_save(pubkey, &p);
|
|
|
|
} else {
|
|
|
|
memset(pubkey, 0, sizeof(*pubkey));
|
Eliminate multiple-returns from secp256k1.c.
Goto, multiple returns, continue, and/or multiple breaks in a
loop are often used to build complex or non-local control
flow in software.
(They're all basically the same thing, and anyone axiomatically
opposing goto and not the rest is probably cargo-culting from
the title of Dijkstra's essay without thinking hard about it.)
Personally, I think the current use of these constructs in the
code base is fine: no where are we using them to create control-
flow that couldn't easily be described in plain English, which
is hard to read or reason about, or which looks like a trap for
future developers.
Some, however, prefer a more rules based approach to software
quality. In particular, MISRA forbids all of these constructs,
and for good experience based reasons. Rules also have the
benefit of being machine checkable and surviving individual
developers.
(To be fair-- MISRA also has a process for accommodating code that
breaks the rules for good reason).
I think that in general we should also try to satisfy the rules-
based measures of software quality, except where there is an
objective reason not do: a measurable performance difference,
logic that turns to spaghetti, etc.
Changing out all the multiple returns in secp256k1.c appears to
be basically neutral: Some parts become slightly less clear,
some parts slightly more.
2015-02-17 01:01:48 -08:00
|
|
|
}
|
2013-07-14 17:43:13 +02:00
|
|
|
}
|
2014-10-27 03:27:55 -07:00
|
|
|
|
2013-07-14 17:43:13 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-02-03 17:27:00 -08:00
|
|
|
int secp256k1_ec_privkey_tweak_mul(const secp256k1_context_t* ctx, unsigned char *seckey, const unsigned char *tweak) {
|
2015-01-25 17:32:08 +00:00
|
|
|
secp256k1_scalar_t factor;
|
|
|
|
secp256k1_scalar_t sec;
|
Eliminate multiple-returns from secp256k1.c.
Goto, multiple returns, continue, and/or multiple breaks in a
loop are often used to build complex or non-local control
flow in software.
(They're all basically the same thing, and anyone axiomatically
opposing goto and not the rest is probably cargo-culting from
the title of Dijkstra's essay without thinking hard about it.)
Personally, I think the current use of these constructs in the
code base is fine: no where are we using them to create control-
flow that couldn't easily be described in plain English, which
is hard to read or reason about, or which looks like a trap for
future developers.
Some, however, prefer a more rules based approach to software
quality. In particular, MISRA forbids all of these constructs,
and for good experience based reasons. Rules also have the
benefit of being machine checkable and surviving individual
developers.
(To be fair-- MISRA also has a process for accommodating code that
breaks the rules for good reason).
I think that in general we should also try to satisfy the rules-
based measures of software quality, except where there is an
objective reason not do: a measurable performance difference,
logic that turns to spaghetti, etc.
Changing out all the multiple returns in secp256k1.c appears to
be basically neutral: Some parts become slightly less clear,
some parts slightly more.
2015-02-17 01:01:48 -08:00
|
|
|
int ret = 0;
|
2015-01-25 17:32:08 +00:00
|
|
|
int overflow = 0;
|
2015-09-01 14:22:32 -04:00
|
|
|
VERIFY_CHECK(ctx != NULL);
|
2015-07-18 16:29:10 -04:00
|
|
|
ARG_CHECK(seckey != NULL);
|
|
|
|
ARG_CHECK(tweak != NULL);
|
2015-02-03 17:27:00 -08:00
|
|
|
(void)ctx;
|
2014-08-18 23:07:46 +02:00
|
|
|
|
2014-10-29 00:35:09 -07:00
|
|
|
secp256k1_scalar_set_b32(&factor, tweak, &overflow);
|
|
|
|
secp256k1_scalar_set_b32(&sec, seckey, NULL);
|
2015-01-25 17:32:08 +00:00
|
|
|
ret = secp256k1_eckey_privkey_tweak_mul(&sec, &factor) && !overflow;
|
2013-07-14 17:43:13 +02:00
|
|
|
if (ret) {
|
2014-10-29 00:35:09 -07:00
|
|
|
secp256k1_scalar_get_b32(seckey, &sec);
|
2014-10-27 03:27:55 -07:00
|
|
|
}
|
|
|
|
|
2014-10-28 04:08:15 -07:00
|
|
|
secp256k1_scalar_clear(&sec);
|
|
|
|
secp256k1_scalar_clear(&factor);
|
2013-07-14 17:43:13 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-07-20 13:36:55 -04:00
|
|
|
int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context_t* ctx, secp256k1_pubkey_t *pubkey, const unsigned char *tweak) {
|
2015-01-25 17:32:08 +00:00
|
|
|
secp256k1_ge_t p;
|
|
|
|
secp256k1_scalar_t factor;
|
Eliminate multiple-returns from secp256k1.c.
Goto, multiple returns, continue, and/or multiple breaks in a
loop are often used to build complex or non-local control
flow in software.
(They're all basically the same thing, and anyone axiomatically
opposing goto and not the rest is probably cargo-culting from
the title of Dijkstra's essay without thinking hard about it.)
Personally, I think the current use of these constructs in the
code base is fine: no where are we using them to create control-
flow that couldn't easily be described in plain English, which
is hard to read or reason about, or which looks like a trap for
future developers.
Some, however, prefer a more rules based approach to software
quality. In particular, MISRA forbids all of these constructs,
and for good experience based reasons. Rules also have the
benefit of being machine checkable and surviving individual
developers.
(To be fair-- MISRA also has a process for accommodating code that
breaks the rules for good reason).
I think that in general we should also try to satisfy the rules-
based measures of software quality, except where there is an
objective reason not do: a measurable performance difference,
logic that turns to spaghetti, etc.
Changing out all the multiple returns in secp256k1.c appears to
be basically neutral: Some parts become slightly less clear,
some parts slightly more.
2015-02-17 01:01:48 -08:00
|
|
|
int ret = 0;
|
2015-01-25 17:32:08 +00:00
|
|
|
int overflow = 0;
|
2015-09-01 14:22:32 -04:00
|
|
|
VERIFY_CHECK(ctx != NULL);
|
2015-07-18 16:29:10 -04:00
|
|
|
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
|
|
|
|
ARG_CHECK(pubkey != NULL);
|
|
|
|
ARG_CHECK(tweak != NULL);
|
2014-08-18 23:07:46 +02:00
|
|
|
|
2014-11-26 17:26:39 +01:00
|
|
|
secp256k1_scalar_set_b32(&factor, tweak, &overflow);
|
2015-07-18 16:29:10 -04:00
|
|
|
if (!overflow && secp256k1_pubkey_load(ctx, &p, pubkey)) {
|
2015-07-20 13:36:55 -04:00
|
|
|
ret = secp256k1_eckey_pubkey_tweak_mul(&ctx->ecmult_ctx, &p, &factor);
|
Eliminate multiple-returns from secp256k1.c.
Goto, multiple returns, continue, and/or multiple breaks in a
loop are often used to build complex or non-local control
flow in software.
(They're all basically the same thing, and anyone axiomatically
opposing goto and not the rest is probably cargo-culting from
the title of Dijkstra's essay without thinking hard about it.)
Personally, I think the current use of these constructs in the
code base is fine: no where are we using them to create control-
flow that couldn't easily be described in plain English, which
is hard to read or reason about, or which looks like a trap for
future developers.
Some, however, prefer a more rules based approach to software
quality. In particular, MISRA forbids all of these constructs,
and for good experience based reasons. Rules also have the
benefit of being machine checkable and surviving individual
developers.
(To be fair-- MISRA also has a process for accommodating code that
breaks the rules for good reason).
I think that in general we should also try to satisfy the rules-
based measures of software quality, except where there is an
objective reason not do: a measurable performance difference,
logic that turns to spaghetti, etc.
Changing out all the multiple returns in secp256k1.c appears to
be basically neutral: Some parts become slightly less clear,
some parts slightly more.
2015-02-17 01:01:48 -08:00
|
|
|
if (ret) {
|
2015-07-20 13:36:55 -04:00
|
|
|
secp256k1_pubkey_save(pubkey, &p);
|
|
|
|
} else {
|
|
|
|
memset(pubkey, 0, sizeof(*pubkey));
|
Eliminate multiple-returns from secp256k1.c.
Goto, multiple returns, continue, and/or multiple breaks in a
loop are often used to build complex or non-local control
flow in software.
(They're all basically the same thing, and anyone axiomatically
opposing goto and not the rest is probably cargo-culting from
the title of Dijkstra's essay without thinking hard about it.)
Personally, I think the current use of these constructs in the
code base is fine: no where are we using them to create control-
flow that couldn't easily be described in plain English, which
is hard to read or reason about, or which looks like a trap for
future developers.
Some, however, prefer a more rules based approach to software
quality. In particular, MISRA forbids all of these constructs,
and for good experience based reasons. Rules also have the
benefit of being machine checkable and surviving individual
developers.
(To be fair-- MISRA also has a process for accommodating code that
breaks the rules for good reason).
I think that in general we should also try to satisfy the rules-
based measures of software quality, except where there is an
objective reason not do: a measurable performance difference,
logic that turns to spaghetti, etc.
Changing out all the multiple returns in secp256k1.c appears to
be basically neutral: Some parts become slightly less clear,
some parts slightly more.
2015-02-17 01:01:48 -08:00
|
|
|
}
|
2013-05-27 01:18:48 +02:00
|
|
|
}
|
2014-10-27 03:27:55 -07:00
|
|
|
|
2013-05-27 01:18:48 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-08-28 01:50:47 +02:00
|
|
|
int secp256k1_ec_privkey_export(const secp256k1_context_t* ctx, unsigned char *privkey, int *privkeylen, const unsigned char *seckey, int compressed) {
|
2015-01-25 17:32:08 +00:00
|
|
|
secp256k1_scalar_t key;
|
Eliminate multiple-returns from secp256k1.c.
Goto, multiple returns, continue, and/or multiple breaks in a
loop are often used to build complex or non-local control
flow in software.
(They're all basically the same thing, and anyone axiomatically
opposing goto and not the rest is probably cargo-culting from
the title of Dijkstra's essay without thinking hard about it.)
Personally, I think the current use of these constructs in the
code base is fine: no where are we using them to create control-
flow that couldn't easily be described in plain English, which
is hard to read or reason about, or which looks like a trap for
future developers.
Some, however, prefer a more rules based approach to software
quality. In particular, MISRA forbids all of these constructs,
and for good experience based reasons. Rules also have the
benefit of being machine checkable and surviving individual
developers.
(To be fair-- MISRA also has a process for accommodating code that
breaks the rules for good reason).
I think that in general we should also try to satisfy the rules-
based measures of software quality, except where there is an
objective reason not do: a measurable performance difference,
logic that turns to spaghetti, etc.
Changing out all the multiple returns in secp256k1.c appears to
be basically neutral: Some parts become slightly less clear,
some parts slightly more.
2015-02-17 01:01:48 -08:00
|
|
|
int ret = 0;
|
2015-09-01 14:22:32 -04:00
|
|
|
VERIFY_CHECK(ctx != NULL);
|
2015-07-18 16:29:10 -04:00
|
|
|
ARG_CHECK(seckey != NULL);
|
|
|
|
ARG_CHECK(privkey != NULL);
|
|
|
|
ARG_CHECK(privkeylen != NULL);
|
|
|
|
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
2014-08-18 23:07:46 +02:00
|
|
|
|
2014-10-29 00:35:09 -07:00
|
|
|
secp256k1_scalar_set_b32(&key, seckey, NULL);
|
2015-02-03 17:27:00 -08:00
|
|
|
ret = secp256k1_eckey_privkey_serialize(&ctx->ecmult_gen_ctx, privkey, privkeylen, &key, compressed);
|
2014-10-28 04:08:15 -07:00
|
|
|
secp256k1_scalar_clear(&key);
|
2013-05-05 05:12:43 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-02-03 17:27:00 -08:00
|
|
|
int secp256k1_ec_privkey_import(const secp256k1_context_t* ctx, unsigned char *seckey, const unsigned char *privkey, int privkeylen) {
|
2015-01-25 17:32:08 +00:00
|
|
|
secp256k1_scalar_t key;
|
Eliminate multiple-returns from secp256k1.c.
Goto, multiple returns, continue, and/or multiple breaks in a
loop are often used to build complex or non-local control
flow in software.
(They're all basically the same thing, and anyone axiomatically
opposing goto and not the rest is probably cargo-culting from
the title of Dijkstra's essay without thinking hard about it.)
Personally, I think the current use of these constructs in the
code base is fine: no where are we using them to create control-
flow that couldn't easily be described in plain English, which
is hard to read or reason about, or which looks like a trap for
future developers.
Some, however, prefer a more rules based approach to software
quality. In particular, MISRA forbids all of these constructs,
and for good experience based reasons. Rules also have the
benefit of being machine checkable and surviving individual
developers.
(To be fair-- MISRA also has a process for accommodating code that
breaks the rules for good reason).
I think that in general we should also try to satisfy the rules-
based measures of software quality, except where there is an
objective reason not do: a measurable performance difference,
logic that turns to spaghetti, etc.
Changing out all the multiple returns in secp256k1.c appears to
be basically neutral: Some parts become slightly less clear,
some parts slightly more.
2015-02-17 01:01:48 -08:00
|
|
|
int ret = 0;
|
2015-07-18 16:29:10 -04:00
|
|
|
ARG_CHECK(seckey != NULL);
|
|
|
|
ARG_CHECK(privkey != NULL);
|
2015-02-03 17:27:00 -08:00
|
|
|
(void)ctx;
|
2014-08-18 23:07:46 +02:00
|
|
|
|
2015-01-25 17:32:08 +00:00
|
|
|
ret = secp256k1_eckey_privkey_parse(&key, privkey, privkeylen);
|
Eliminate multiple-returns from secp256k1.c.
Goto, multiple returns, continue, and/or multiple breaks in a
loop are often used to build complex or non-local control
flow in software.
(They're all basically the same thing, and anyone axiomatically
opposing goto and not the rest is probably cargo-culting from
the title of Dijkstra's essay without thinking hard about it.)
Personally, I think the current use of these constructs in the
code base is fine: no where are we using them to create control-
flow that couldn't easily be described in plain English, which
is hard to read or reason about, or which looks like a trap for
future developers.
Some, however, prefer a more rules based approach to software
quality. In particular, MISRA forbids all of these constructs,
and for good experience based reasons. Rules also have the
benefit of being machine checkable and surviving individual
developers.
(To be fair-- MISRA also has a process for accommodating code that
breaks the rules for good reason).
I think that in general we should also try to satisfy the rules-
based measures of software quality, except where there is an
objective reason not do: a measurable performance difference,
logic that turns to spaghetti, etc.
Changing out all the multiple returns in secp256k1.c appears to
be basically neutral: Some parts become slightly less clear,
some parts slightly more.
2015-02-17 01:01:48 -08:00
|
|
|
if (ret) {
|
2014-10-29 00:35:09 -07:00
|
|
|
secp256k1_scalar_get_b32(seckey, &key);
|
Eliminate multiple-returns from secp256k1.c.
Goto, multiple returns, continue, and/or multiple breaks in a
loop are often used to build complex or non-local control
flow in software.
(They're all basically the same thing, and anyone axiomatically
opposing goto and not the rest is probably cargo-culting from
the title of Dijkstra's essay without thinking hard about it.)
Personally, I think the current use of these constructs in the
code base is fine: no where are we using them to create control-
flow that couldn't easily be described in plain English, which
is hard to read or reason about, or which looks like a trap for
future developers.
Some, however, prefer a more rules based approach to software
quality. In particular, MISRA forbids all of these constructs,
and for good experience based reasons. Rules also have the
benefit of being machine checkable and surviving individual
developers.
(To be fair-- MISRA also has a process for accommodating code that
breaks the rules for good reason).
I think that in general we should also try to satisfy the rules-
based measures of software quality, except where there is an
objective reason not do: a measurable performance difference,
logic that turns to spaghetti, etc.
Changing out all the multiple returns in secp256k1.c appears to
be basically neutral: Some parts become slightly less clear,
some parts slightly more.
2015-02-17 01:01:48 -08:00
|
|
|
}
|
2014-10-28 04:08:15 -07:00
|
|
|
secp256k1_scalar_clear(&key);
|
2013-05-05 05:12:43 +02:00
|
|
|
return ret;
|
|
|
|
}
|
2015-04-15 21:35:50 +00:00
|
|
|
|
|
|
|
int secp256k1_context_randomize(secp256k1_context_t* ctx, const unsigned char *seed32) {
|
2015-09-01 14:22:32 -04:00
|
|
|
VERIFY_CHECK(ctx != NULL);
|
2015-07-18 16:29:10 -04:00
|
|
|
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
2015-04-15 21:35:50 +00:00
|
|
|
secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32);
|
|
|
|
return 1;
|
|
|
|
}
|
2015-06-29 15:06:28 -05:00
|
|
|
|
2015-08-28 01:50:47 +02:00
|
|
|
int secp256k1_ec_pubkey_combine(const secp256k1_context_t* ctx, secp256k1_pubkey_t *pubnonce, const secp256k1_pubkey_t * const *pubnonces, int n) {
|
2015-07-24 15:44:49 +02:00
|
|
|
int i;
|
|
|
|
secp256k1_gej_t Qj;
|
|
|
|
secp256k1_ge_t Q;
|
|
|
|
|
|
|
|
ARG_CHECK(pubnonce != NULL);
|
|
|
|
ARG_CHECK(n >= 1);
|
|
|
|
ARG_CHECK(pubnonces != NULL);
|
|
|
|
|
|
|
|
secp256k1_gej_set_infinity(&Qj);
|
|
|
|
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
secp256k1_pubkey_load(ctx, &Q, pubnonces[i]);
|
|
|
|
secp256k1_gej_add_ge(&Qj, &Qj, &Q);
|
|
|
|
}
|
|
|
|
if (secp256k1_gej_is_infinity(&Qj)) {
|
|
|
|
memset(pubnonce, 0, sizeof(*pubnonce));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
secp256k1_ge_set_gej(&Q, &Qj);
|
|
|
|
secp256k1_pubkey_save(pubnonce, &Q);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2015-06-29 15:06:28 -05:00
|
|
|
#ifdef ENABLE_MODULE_ECDH
|
|
|
|
# include "modules/ecdh/main_impl.h"
|
|
|
|
#endif
|
2015-07-24 15:44:49 +02:00
|
|
|
|
|
|
|
#ifdef ENABLE_MODULE_SCHNORR
|
|
|
|
# include "modules/schnorr/main_impl.h"
|
|
|
|
#endif
|
2015-08-27 03:42:57 +02:00
|
|
|
|
|
|
|
#ifdef ENABLE_MODULE_RECOVERY
|
|
|
|
# include "modules/recovery/main_impl.h"
|
|
|
|
#endif
|