Browse Source

fix a security issue

pull/2206/head
Max Lv 10 years ago
parent
commit
ed53fb6c54
4 changed files with 25 additions and 23 deletions
  1. 14
      src/bitcoin.c
  2. 4
      src/bitcoin.h
  3. 15
      src/local.c
  4. 15
      src/server.c

14
src/bitcoin.c

@ -512,7 +512,7 @@ static int priv_key_b58_to_address(const char *priv_key_b58,
// -1 : invalid private key
// 1 : compressed
// 0 : uncompressed
static int isCompressedAddress(const char *priv_key_b58, const char *address)
static int isCompressedAddress(const char *priv_key_b58, const char *address, const size_t addr_len)
{
int is_compressed_pubkey;
char buf[64];
@ -526,7 +526,7 @@ static int isCompressedAddress(const char *priv_key_b58, const char *address)
if (res != 1) {
return -1;
}
if (memcmp(buf, address, strlen(address)) == 0) {
if (memcmp(buf, address, addr_len) == 0) {
return 1; // compressed
}
@ -538,7 +538,7 @@ static int isCompressedAddress(const char *priv_key_b58, const char *address)
if (res != 1) {
return -1;
}
if (memcmp(buf, address, strlen(address)) == 0) {
if (memcmp(buf, address, addr_len) == 0) {
return 0; // uncompressed
}
@ -657,15 +657,15 @@ static int sign_message(uint8_t *signature_65,
int bitcoin_sign_message(unsigned char *buf_65,
const void *msg, const size_t msg_len,
const char *priv_key_b58, const char *address)
const char *priv_key_b58, const char *address, const size_t addr_len)
{
int is_compressed = isCompressedAddress(priv_key_b58, address);
int is_compressed = isCompressedAddress(priv_key_b58, address, addr_len);
return sign_message(buf_65, (uint8_t *)msg, msg_len,
priv_key_b58, is_compressed);
}
int bitcoin_verify_message(const char *address, const unsigned char *sig,
const void *msg, const size_t msglen)
const void *msg, const size_t msglen, const size_t addr_len)
{
EC_KEY *pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
uint8_t hash[32] = { 0 };
@ -693,7 +693,7 @@ int bitcoin_verify_message(const char *address, const unsigned char *sig,
is_compressed_pubkey ?
POINT_CONVERSION_COMPRESSED : POINT_CONVERSION_UNCOMPRESSED,
BITCOIN_ADDRESS_PREFIX_PUBKEY, ecprot);
if (memcmp(address, ecprot, strlen(address)) == 0) {
if (memcmp(address, ecprot, addr_len) == 0) {
fOK = 1;
}

4
src/bitcoin.h

@ -26,10 +26,10 @@
extern int bitcoin_sign_message(unsigned char *buf_65,
const void *msg, const size_t msg_len,
const char *priv_key_b58, const char *address);
const char *priv_key_b58, const char *address, const size_t addr_len);
extern int bitcoin_verify_message(const char *address, const unsigned char *sig_65,
const void *msg, const size_t msglen);
const void *msg, const size_t msg_len, const size_t addr_len);
struct btc_client;
struct btc_list;

15
src/local.c

@ -435,17 +435,17 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
if (bitcoin_address != NULL && bitcoin_privkey != NULL) {
/*
* bitcoin information:
* +-----------+-----------+----------+
* | Signature | Timestamp | Address |
* +-----------+-----------+----------+
* | 65 | 4 | String |
* +-----------+-----------+----------+
* +-----------+-----------+---------+-----------+
* | Signature | Timestamp | AddLen | Address |
* +-----------+-----------+---------+-----------+
* | 65 | 4 | 1 | 26 - 35 |
* +-----------+-----------+---------+-----------+
*/
uint32_t now = (uint32_t)time(NULL);
uint8_t msg[4] = { (uint8_t)(now >> 24), (uint8_t)(now >> 16),
(uint8_t)(now >> 8), (uint8_t)(now >> 0) };
uint8_t sig[65] = { 0 }; // signature buf size always 65 bytes
if (!bitcoin_sign_message(sig, msg, sizeof(msg), bitcoin_privkey, bitcoin_address)) {
if (!bitcoin_sign_message(sig, msg, sizeof(msg), bitcoin_privkey, bitcoin_address, strlen(bitcoin_address))) {
FATAL("bitcoin sign message fail");
}
size_t addr_len_ori = addr_len;
@ -453,9 +453,10 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
addr_len += 65;
memcpy(ss_addr_to_send + addr_len, msg, sizeof(msg));
addr_len += 4;
ss_addr_to_send[addr_len] = (uint8_t)strlen(bitcoin_address);
addr_len += 1;
memcpy(ss_addr_to_send + addr_len, bitcoin_address, strlen(bitcoin_address));
addr_len += strlen(bitcoin_address);
ss_addr_to_send[addr_len++] = '\0';
bitcoin_len = addr_len - addr_len_ori;
ss_addr_to_send[0] |= 0x10; // set bitcoin flag

15
src/server.c

@ -568,17 +568,18 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
}
/*
* bitcoin information:
* +-----------+-----------+----------+
* | Signature | Timestamp | Address |
* +-----------+-----------+----------+
* | 65 | 4 | String |
* +-----------+-----------+----------+
* +-----------+-----------+---------+-----------+
* | Signature | Timestamp | AddLen | Address |
* +-----------+-----------+---------+-----------+
* | 65 | 4 | 1 | 26 - 35 |
* +-----------+-----------+---------+-----------+
*/
char *signature = server->buf + offset;
uint8_t *t = (uint8_t *)server->buf + offset + 65;
uint32_t ts = ((uint32_t)*(t + 0) << 24) + ((uint32_t)*(t + 1) << 16)
+ ((uint32_t)*(t + 2) << 8) + ((uint32_t)*(t + 3) << 0);
char *address = server->buf + offset + 65 + 4;
int addr_len = server->buf[offset + 64 + 4];
char *address = server->buf + offset + 65 + 4 + 1;
int64_t ts_offset = (int64_t)time(NULL) - (int64_t)ts;
if (labs(ts_offset) > 60 * 30) {
if (verbose) {
@ -588,7 +589,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
close_and_free_server(EV_A_ server);
return;
}
if (!bitcoin_verify_message(address, (uint8_t *)signature, t, 4)) {
if (!bitcoin_verify_message(address, (uint8_t *)signature, t, 4, addr_len)) {
if (verbose) {
LOGE("invalid signature, address: %s", address);
}

Loading…
Cancel
Save