Add strict checks to hex to binary conversions.
The main goal is to catch misuse of the obsolete PrivateKey and PublicKey statements.
This commit is contained in:
parent
3bd810ea79
commit
c4940a5c88
5 changed files with 38 additions and 12 deletions
10
lib/utils.c
10
lib/utils.c
|
@ -32,12 +32,14 @@ static int charhex2bin(char c) {
|
||||||
return toupper(c) - 'A' + 10;
|
return toupper(c) - 'A' + 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hex2bin(char *src, char *dst, int length) {
|
||||||
void hex2bin(char *src, char *dst, int length) {
|
for(int i = 0; i < length; i++) {
|
||||||
int i;
|
if(!isxdigit(src[i * 2]) || !isxdigit(src[i * 2 + 1]))
|
||||||
for(i = 0; i < length; i++)
|
return false;
|
||||||
dst[i] = charhex2bin(src[i * 2]) * 16 + charhex2bin(src[i * 2 + 1]);
|
dst[i] = charhex2bin(src[i * 2]) * 16 + charhex2bin(src[i * 2 + 1]);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void bin2hex(char *src, char *dst, int length) {
|
void bin2hex(char *src, char *dst, int length) {
|
||||||
int i;
|
int i;
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#ifndef __TINC_UTILS_H__
|
#ifndef __TINC_UTILS_H__
|
||||||
#define __TINC_UTILS_H__
|
#define __TINC_UTILS_H__
|
||||||
|
|
||||||
extern void hex2bin(char *src, char *dst, int length);
|
extern bool hex2bin(char *src, char *dst, int length);
|
||||||
extern void bin2hex(char *src, char *dst, int length);
|
extern void bin2hex(char *src, char *dst, int length);
|
||||||
|
|
||||||
#ifdef HAVE_MINGW
|
#ifdef HAVE_MINGW
|
||||||
|
|
|
@ -66,7 +66,10 @@ bool read_rsa_public_key(connection_t *c) {
|
||||||
/* First, check for simple PublicKey statement */
|
/* First, check for simple PublicKey statement */
|
||||||
|
|
||||||
if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &key)) {
|
if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &key)) {
|
||||||
BN_hex2bn(&c->rsa_key->n, key);
|
if(BN_hex2bn(&c->rsa_key->n, key) != strlen(key)) {
|
||||||
|
logger(LOG_ERR, "Invalid PublicKey for %s!", c->name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
BN_hex2bn(&c->rsa_key->e, "FFFF");
|
BN_hex2bn(&c->rsa_key->e, "FFFF");
|
||||||
free(key);
|
free(key);
|
||||||
return true;
|
return true;
|
||||||
|
@ -169,8 +172,14 @@ static bool read_rsa_private_key(void) {
|
||||||
}
|
}
|
||||||
myself->connection->rsa_key = RSA_new();
|
myself->connection->rsa_key = RSA_new();
|
||||||
// RSA_blinding_on(myself->connection->rsa_key, NULL);
|
// RSA_blinding_on(myself->connection->rsa_key, NULL);
|
||||||
BN_hex2bn(&myself->connection->rsa_key->d, key);
|
if(BN_hex2bn(&myself->connection->rsa_key->d, key) != strlen(key)) {
|
||||||
BN_hex2bn(&myself->connection->rsa_key->n, pubkey);
|
logger(LOG_ERR, "Invalid PrivateKey for myself!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(BN_hex2bn(&myself->connection->rsa_key->n, pubkey) != strlen(pubkey)) {
|
||||||
|
logger(LOG_ERR, "Invalid PublicKey for myself!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
BN_hex2bn(&myself->connection->rsa_key->e, "FFFF");
|
BN_hex2bn(&myself->connection->rsa_key->e, "FFFF");
|
||||||
free(key);
|
free(key);
|
||||||
free(pubkey);
|
free(pubkey);
|
||||||
|
|
|
@ -308,7 +308,10 @@ bool metakey_h(connection_t *c) {
|
||||||
|
|
||||||
/* Convert the challenge from hexadecimal back to binary */
|
/* Convert the challenge from hexadecimal back to binary */
|
||||||
|
|
||||||
hex2bin(buffer, buffer, len);
|
if(!hex2bin(buffer, buffer, len)) {
|
||||||
|
logger(LOG_ERR, "Got bad %s from %s(%s): %s", "METAKEY", c->name, c->hostname, "invalid key");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Decrypt the meta key */
|
/* Decrypt the meta key */
|
||||||
|
|
||||||
|
@ -426,7 +429,10 @@ bool challenge_h(connection_t *c) {
|
||||||
|
|
||||||
/* Convert the challenge from hexadecimal back to binary */
|
/* Convert the challenge from hexadecimal back to binary */
|
||||||
|
|
||||||
hex2bin(buffer, c->mychallenge, len);
|
if(!hex2bin(buffer, c->mychallenge, len)) {
|
||||||
|
logger(LOG_ERR, "Got bad %s from %s(%s): %s", "CHALLENGE", c->name, c->hostname, "invalid challenge");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
c->allow_request = CHAL_REPLY;
|
c->allow_request = CHAL_REPLY;
|
||||||
|
|
||||||
|
@ -480,7 +486,10 @@ bool chal_reply_h(connection_t *c) {
|
||||||
|
|
||||||
/* Convert the hash to binary format */
|
/* Convert the hash to binary format */
|
||||||
|
|
||||||
hex2bin(hishash, hishash, c->outdigest->md_size);
|
if(!hex2bin(hishash, hishash, c->outdigest->md_size)) {
|
||||||
|
logger(LOG_ERR, "Got bad %s from %s(%s): %s", "CHAL_REPLY", c->name, c->hostname, "invalid hash");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Calculate the hash from the challenge we sent */
|
/* Calculate the hash from the challenge we sent */
|
||||||
|
|
||||||
|
|
|
@ -240,10 +240,16 @@ bool ans_key_h(connection_t *c) {
|
||||||
return send_request(to->nexthop->connection, "%s", c->buffer);
|
return send_request(to->nexthop->connection, "%s", c->buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Don't use key material until every check has passed. */
|
||||||
|
from->status.validkey = false;
|
||||||
|
|
||||||
/* Update our copy of the origin's packet key */
|
/* Update our copy of the origin's packet key */
|
||||||
from->outkey = xrealloc(from->outkey, strlen(key) / 2);
|
from->outkey = xrealloc(from->outkey, strlen(key) / 2);
|
||||||
from->outkeylength = strlen(key) / 2;
|
from->outkeylength = strlen(key) / 2;
|
||||||
hex2bin(key, from->outkey, from->outkeylength);
|
if(!hex2bin(key, from->outkey, from->outkeylength)) {
|
||||||
|
logger(LOG_ERR, "Got bad %s from %s(%s): %s", "ANS_KEY", from->name, from->hostname, "invalid key");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check and lookup cipher and digest algorithms */
|
/* Check and lookup cipher and digest algorithms */
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue