Merge commits '88e80722 ff8edf89 f29a3270 a7a7bfaf a01a7d86 b1579cf5 ad7433b1 233822d8 5fbff5d3 2b77240b 1bff2005 e1817a6f 5596ec5c 8ebe5c52 1cca7c17 1b21aa51 cbd25559 09b1d466 57573187 8962fc95 9d1b458d eb8749fc 6048e6c0 ' into temp-merge-1222
This commit is contained in:
@@ -14,8 +14,7 @@
|
||||
#include <secp256k1.h>
|
||||
#include <secp256k1_ecdh.h>
|
||||
|
||||
#include "random.h"
|
||||
|
||||
#include "examples_util.h"
|
||||
|
||||
int main(void) {
|
||||
unsigned char seckey1[32];
|
||||
@@ -112,12 +111,12 @@ int main(void) {
|
||||
* example through "out of bounds" array access (see Heartbleed), Or the OS
|
||||
* swapping them to disk. Hence, we overwrite the secret key buffer with zeros.
|
||||
*
|
||||
* TODO: Prevent these writes from being optimized out, as any good compiler
|
||||
* Here we are preventing these writes from being optimized out, as any good compiler
|
||||
* will remove any writes that aren't used. */
|
||||
memset(seckey1, 0, sizeof(seckey1));
|
||||
memset(seckey2, 0, sizeof(seckey2));
|
||||
memset(shared_secret1, 0, sizeof(shared_secret1));
|
||||
memset(shared_secret2, 0, sizeof(shared_secret2));
|
||||
secure_erase(seckey1, sizeof(seckey1));
|
||||
secure_erase(seckey2, sizeof(seckey2));
|
||||
secure_erase(shared_secret1, sizeof(shared_secret1));
|
||||
secure_erase(shared_secret2, sizeof(shared_secret2));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -13,9 +13,7 @@
|
||||
|
||||
#include <secp256k1.h>
|
||||
|
||||
#include "random.h"
|
||||
|
||||
|
||||
#include "examples_util.h"
|
||||
|
||||
int main(void) {
|
||||
/* Instead of signing the message directly, we must sign a 32-byte hash.
|
||||
@@ -34,7 +32,7 @@ int main(void) {
|
||||
unsigned char compressed_pubkey[33];
|
||||
unsigned char serialized_signature[64];
|
||||
size_t len;
|
||||
int is_signature_valid;
|
||||
int is_signature_valid, is_signature_valid2;
|
||||
int return_val;
|
||||
secp256k1_pubkey pubkey;
|
||||
secp256k1_ecdsa_signature sig;
|
||||
@@ -116,18 +114,26 @@ int main(void) {
|
||||
printf("Signature: ");
|
||||
print_hex(serialized_signature, sizeof(serialized_signature));
|
||||
|
||||
|
||||
/* This will clear everything from the context and free the memory */
|
||||
secp256k1_context_destroy(ctx);
|
||||
|
||||
/* Bonus example: if all we need is signature verification (and no key
|
||||
generation or signing), we don't need to use a context created via
|
||||
secp256k1_context_create(). We can simply use the static (i.e., global)
|
||||
context secp256k1_context_static. See its description in
|
||||
include/secp256k1.h for details. */
|
||||
is_signature_valid2 = secp256k1_ecdsa_verify(secp256k1_context_static,
|
||||
&sig, msg_hash, &pubkey);
|
||||
assert(is_signature_valid2 == is_signature_valid);
|
||||
|
||||
/* It's best practice to try to clear secrets from memory after using them.
|
||||
* This is done because some bugs can allow an attacker to leak memory, for
|
||||
* example through "out of bounds" array access (see Heartbleed), Or the OS
|
||||
* swapping them to disk. Hence, we overwrite the secret key buffer with zeros.
|
||||
*
|
||||
* TODO: Prevent these writes from being optimized out, as any good compiler
|
||||
* Here we are preventing these writes from being optimized out, as any good compiler
|
||||
* will remove any writes that aren't used. */
|
||||
memset(seckey, 0, sizeof(seckey));
|
||||
secure_erase(seckey, sizeof(seckey));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -71,3 +71,32 @@ static void print_hex(unsigned char* data, size_t size) {
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// For SecureZeroMemory
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
/* Cleanses memory to prevent leaking sensitive info. Won't be optimized out. */
|
||||
static SECP256K1_INLINE void secure_erase(void *ptr, size_t len) {
|
||||
#if defined(_MSC_VER)
|
||||
/* SecureZeroMemory is guaranteed not to be optimized out by MSVC. */
|
||||
SecureZeroMemory(ptr, len);
|
||||
#elif defined(__GNUC__)
|
||||
/* We use a memory barrier that scares the compiler away from optimizing out the memset.
|
||||
*
|
||||
* Quoting Adam Langley <agl@google.com> in commit ad1907fe73334d6c696c8539646c21b11178f20f
|
||||
* in BoringSSL (ISC License):
|
||||
* As best as we can tell, this is sufficient to break any optimisations that
|
||||
* might try to eliminate "superfluous" memsets.
|
||||
* This method used in memzero_explicit() the Linux kernel, too. Its advantage is that it is
|
||||
* pretty efficient, because the compiler can still implement the memset() efficently,
|
||||
* just not remove it entirely. See "Dead Store Elimination (Still) Considered Harmful" by
|
||||
* Yang et al. (USENIX Security 2017) for more background.
|
||||
*/
|
||||
memset(ptr, 0, len);
|
||||
__asm__ __volatile__("" : : "r"(ptr) : "memory");
|
||||
#else
|
||||
void *(*volatile const volatile_memset)(void *, int, size_t) = memset;
|
||||
volatile_memset(ptr, 0, len);
|
||||
#endif
|
||||
}
|
||||
@@ -14,11 +14,13 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <secp256k1.h>
|
||||
#include <secp256k1_schnorrsig.h>
|
||||
#include <secp256k1_musig.h>
|
||||
|
||||
#include "random.h"
|
||||
#include "examples_util.h"
|
||||
|
||||
struct signer_secrets {
|
||||
secp256k1_keypair keypair;
|
||||
@@ -34,7 +36,7 @@ struct signer {
|
||||
/* Number of public keys involved in creating the aggregate signature */
|
||||
#define N_SIGNERS 3
|
||||
/* Create a key pair, store it in signer_secrets->keypair and signer->pubkey */
|
||||
int create_keypair(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, struct signer *signer) {
|
||||
static int create_keypair(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, struct signer *signer) {
|
||||
unsigned char seckey[32];
|
||||
while (1) {
|
||||
if (!fill_random(seckey, sizeof(seckey))) {
|
||||
@@ -53,7 +55,7 @@ int create_keypair(const secp256k1_context* ctx, struct signer_secrets *signer_s
|
||||
|
||||
/* Tweak the pubkey corresponding to the provided keyagg cache, update the cache
|
||||
* and return the tweaked aggregate pk. */
|
||||
int tweak(const secp256k1_context* ctx, secp256k1_xonly_pubkey *agg_pk, secp256k1_musig_keyagg_cache *cache) {
|
||||
static int tweak(const secp256k1_context* ctx, secp256k1_xonly_pubkey *agg_pk, secp256k1_musig_keyagg_cache *cache) {
|
||||
secp256k1_pubkey output_pk;
|
||||
unsigned char plain_tweak[32] = "this could be a BIP32 tweak....";
|
||||
unsigned char xonly_tweak[32] = "this could be a taproot tweak..";
|
||||
@@ -91,7 +93,7 @@ int tweak(const secp256k1_context* ctx, secp256k1_xonly_pubkey *agg_pk, secp256k
|
||||
}
|
||||
|
||||
/* Sign a message hash with the given key pairs and store the result in sig */
|
||||
int sign(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, struct signer *signer, const secp256k1_musig_keyagg_cache *cache, const unsigned char *msg32, unsigned char *sig64) {
|
||||
static int sign(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, struct signer *signer, const secp256k1_musig_keyagg_cache *cache, const unsigned char *msg32, unsigned char *sig64) {
|
||||
int i;
|
||||
const secp256k1_musig_pubnonce *pubnonces[N_SIGNERS];
|
||||
const secp256k1_musig_partial_sig *partial_sigs[N_SIGNERS];
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include <secp256k1_extrakeys.h>
|
||||
#include <secp256k1_schnorrsig.h>
|
||||
|
||||
#include "random.h"
|
||||
#include "examples_util.h"
|
||||
|
||||
int main(void) {
|
||||
unsigned char msg[12] = "Hello World!";
|
||||
@@ -26,7 +26,7 @@ int main(void) {
|
||||
unsigned char auxiliary_rand[32];
|
||||
unsigned char serialized_pubkey[32];
|
||||
unsigned char signature[64];
|
||||
int is_signature_valid;
|
||||
int is_signature_valid, is_signature_valid2;
|
||||
int return_val;
|
||||
secp256k1_xonly_pubkey pubkey;
|
||||
secp256k1_keypair keypair;
|
||||
@@ -135,14 +135,22 @@ int main(void) {
|
||||
/* This will clear everything from the context and free the memory */
|
||||
secp256k1_context_destroy(ctx);
|
||||
|
||||
/* Bonus example: if all we need is signature verification (and no key
|
||||
generation or signing), we don't need to use a context created via
|
||||
secp256k1_context_create(). We can simply use the static (i.e., global)
|
||||
context secp256k1_context_static. See its description in
|
||||
include/secp256k1.h for details. */
|
||||
is_signature_valid2 = secp256k1_schnorrsig_verify(secp256k1_context_static,
|
||||
signature, msg_hash, 32, &pubkey);
|
||||
assert(is_signature_valid2 == is_signature_valid);
|
||||
|
||||
/* It's best practice to try to clear secrets from memory after using them.
|
||||
* This is done because some bugs can allow an attacker to leak memory, for
|
||||
* example through "out of bounds" array access (see Heartbleed), Or the OS
|
||||
* swapping them to disk. Hence, we overwrite the secret key buffer with zeros.
|
||||
*
|
||||
* TODO: Prevent these writes from being optimized out, as any good compiler
|
||||
* Here we are preventing these writes from being optimized out, as any good compiler
|
||||
* will remove any writes that aren't used. */
|
||||
memset(seckey, 0, sizeof(seckey));
|
||||
|
||||
secure_erase(seckey, sizeof(seckey));
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user