Use conditional compilation for cryptographic functions.

This gets rid of the rest of the symbolic links. However, as a consequence, the
crypto header files have now moved to src/, and can no longer contain
library-specific declarations. Therefore, cipher_t, digest_t, ecdh_t, ecdsa_t
and rsa_t are now all opaque types, and only pointers to those types can be
used.
This commit is contained in:
Guus Sliepen 2013-05-01 17:17:22 +02:00
parent e70b5b5bd7
commit 9b9230a0a7
35 changed files with 595 additions and 639 deletions

View file

@ -1,6 +1,6 @@
/*
cipher.c -- Symmetric block cipher handling
Copyright (C) 2007-2012 Guus Sliepen <guus@tinc-vpn.org>
Copyright (C) 2007-2013 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -17,56 +17,67 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "system.h"
#include "../system.h"
#include <openssl/rand.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include "cipher.h"
#include "logger.h"
#include "xalloc.h"
#include "../cipher.h"
#include "../logger.h"
#include "../xalloc.h"
struct cipher {
EVP_CIPHER_CTX ctx;
const EVP_CIPHER *cipher;
struct cipher_counter *counter;
};
typedef struct cipher_counter {
unsigned char counter[EVP_MAX_IV_LENGTH];
unsigned char block[EVP_MAX_IV_LENGTH];
unsigned char counter[CIPHER_MAX_IV_SIZE];
unsigned char block[CIPHER_MAX_IV_SIZE];
int n;
} cipher_counter_t;
static bool cipher_open(cipher_t *cipher) {
static cipher_t *cipher_open(const EVP_CIPHER *evp_cipher) {
cipher_t *cipher = xmalloc_and_zero(sizeof *cipher);
cipher->cipher = evp_cipher;
EVP_CIPHER_CTX_init(&cipher->ctx);
return true;
return cipher;
}
bool cipher_open_by_name(cipher_t *cipher, const char *name) {
cipher->cipher = EVP_get_cipherbyname(name);
cipher_t *cipher_open_by_name(const char *name) {
const EVP_CIPHER *evp_cipher = EVP_get_cipherbyname(name);
if(!evp_cipher) {
logger(DEBUG_ALWAYS, LOG_ERR, "Unknown cipher name '%s'!", name);
return NULL;
}
if(cipher->cipher)
return cipher_open(cipher);
logger(DEBUG_ALWAYS, LOG_ERR, "Unknown cipher name '%s'!", name);
return false;
return cipher_open(evp_cipher);
}
bool cipher_open_by_nid(cipher_t *cipher, int nid) {
cipher->cipher = EVP_get_cipherbynid(nid);
cipher_t *cipher_open_by_nid(int nid) {
const EVP_CIPHER *evp_cipher = EVP_get_cipherbynid(nid);
if(!evp_cipher) {
logger(DEBUG_ALWAYS, LOG_ERR, "Unknown cipher nid %d!", nid);
return NULL;
}
if(cipher->cipher)
return cipher_open(cipher);
logger(DEBUG_ALWAYS, LOG_ERR, "Unknown cipher nid %d!", nid);
return false;
return cipher_open(evp_cipher);
}
bool cipher_open_blowfish_ofb(cipher_t *cipher) {
cipher->cipher = EVP_bf_ofb();
return cipher_open(cipher);
cipher_t *cipher_open_blowfish_ofb(void) {
return cipher_open(EVP_bf_ofb());
}
void cipher_close(cipher_t *cipher) {
if(!cipher)
return;
EVP_CIPHER_CTX_cleanup(&cipher->ctx);
free(cipher->counter);
cipher->counter = NULL;
free(cipher);
}
size_t cipher_keylength(const cipher_t *cipher) {
@ -214,5 +225,5 @@ int cipher_get_nid(const cipher_t *cipher) {
}
bool cipher_active(const cipher_t *cipher) {
return cipher->cipher && cipher->cipher->nid != 0;
return cipher && cipher->cipher && cipher->cipher->nid != 0;
}

View file

@ -1,50 +0,0 @@
/*
cipher.h -- header file cipher.c
Copyright (C) 2007-2012 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_CIPHER_H__
#define __TINC_CIPHER_H__
#include <openssl/evp.h>
#define CIPHER_MAX_BLOCK_SIZE EVP_MAX_BLOCK_LENGTH
#define CIPHER_MAX_KEY_SIZE EVP_MAX_KEY_LENGTH
#define CIPHER_MAX_IV_SIZE EVP_MAX_IV_LENGTH
typedef struct cipher {
EVP_CIPHER_CTX ctx;
const EVP_CIPHER *cipher;
struct cipher_counter *counter;
} cipher_t;
extern bool cipher_open_by_name(cipher_t *, const char *);
extern bool cipher_open_by_nid(cipher_t *, int);
extern bool cipher_open_blowfish_ofb(cipher_t *);
extern void cipher_close(cipher_t *);
extern size_t cipher_keylength(const cipher_t *);
extern bool cipher_set_key(cipher_t *, void *, bool);
extern bool cipher_set_key_from_rsa(cipher_t *, void *, size_t, bool);
extern bool cipher_set_counter(cipher_t *, const void *, size_t);
extern bool cipher_set_counter_key(cipher_t *, void *);
extern bool cipher_encrypt(cipher_t *, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool);
extern bool cipher_decrypt(cipher_t *, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool);
extern bool cipher_counter_xor(cipher_t *, const void *indata, size_t inlen, void *outdata);
extern int cipher_get_nid(const cipher_t *);
extern bool cipher_active(const cipher_t *);
#endif

View file

@ -1,6 +1,6 @@
/*
crypto.c -- Cryptographic miscellaneous functions and initialisation
Copyright (C) 2007 Guus Sliepen <guus@tinc-vpn.org>
Copyright (C) 2007-2013 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -17,13 +17,13 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "system.h"
#include "../system.h"
#include <openssl/rand.h>
#include <openssl/evp.h>
#include <openssl/engine.h>
#include "crypto.h"
#include "../crypto.h"
void crypto_init(void) {
RAND_load_file("/dev/urandom", 1024);

View file

@ -1,27 +0,0 @@
/*
crypto.h -- header for crypto.c
Copyright (C) 2007 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_CRYPTO_H__
#define __TINC_CRYPTO_H__
extern void crypto_init();
extern void crypto_exit();
extern void randomize(void *, size_t);
#endif

View file

@ -1,6 +1,6 @@
/*
digest.c -- Digest handling
Copyright (C) 2007-2012 Guus Sliepen <guus@tinc-vpn.org>
Copyright (C) 2007-2013 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -17,57 +17,55 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "system.h"
#include "utils.h"
#include "xalloc.h"
#include "../system.h"
#include "../utils.h"
#include "../xalloc.h"
#include <openssl/err.h>
#include <openssl/hmac.h>
#include "digest.h"
#include "logger.h"
#include "../digest.h"
#include "../logger.h"
static digest_t *digest_open(const EVP_MD *evp_md, int maclength) {
digest_t *digest = xmalloc_and_zero(sizeof *digest);
digest->digest = evp_md;
static void set_maclength(digest_t *digest, int maclength) {
int digestlen = EVP_MD_size(digest->digest);
if(maclength > digestlen || maclength < 0)
digest->maclength = digestlen;
else
digest->maclength = maclength;
return digest;
}
bool digest_open_by_name(digest_t *digest, const char *name, int maclength) {
digest->digest = EVP_get_digestbyname(name);
digest->key = NULL;
digest_t *digest_open_by_name(const char *name, int maclength) {
const EVP_MD *evp_md = EVP_get_digestbyname(name);
if(!digest->digest) {
if(!evp_md) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "Unknown digest name '%s'!", name);
return false;
}
set_maclength(digest, maclength);
return true;
return digest_open(evp_md, maclength);
}
bool digest_open_by_nid(digest_t *digest, int nid, int maclength) {
digest->digest = EVP_get_digestbynid(nid);
digest->key = NULL;
digest_t *digest_open_by_nid(int nid, int maclength) {
const EVP_MD *evp_md = EVP_get_digestbynid(nid);
if(!digest->digest) {
if(!evp_md) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "Unknown digest nid %d!", nid);
return false;
}
set_maclength(digest, maclength);
return true;
return digest_open(evp_md, maclength);
}
bool digest_open_sha1(digest_t *digest, int maclength) {
digest->digest = EVP_sha1();
digest->key = NULL;
set_maclength(digest, maclength);
return true;
digest_t *digest_open_sha1(int maclength) {
return digest_open(EVP_sha1(), maclength);
}
bool digest_set_key(digest_t *digest, const void *key, size_t len) {
@ -78,8 +76,11 @@ bool digest_set_key(digest_t *digest, const void *key, size_t len) {
}
void digest_close(digest_t *digest) {
if(!digest)
return;
free(digest->key);
digest->key = NULL;
free(digest);
}
bool digest_create(digest_t *digest, const void *indata, size_t inlen, void *outdata) {
@ -123,5 +124,5 @@ size_t digest_length(const digest_t *digest) {
}
bool digest_active(const digest_t *digest) {
return digest->digest && digest->digest->type != 0;
return digest && digest->digest && digest->digest->type != 0;
}

View file

@ -1,6 +1,6 @@
/*
digest.h -- header file digest.c
Copyright (C) 2007-2011 Guus Sliepen <guus@tinc-vpn.org>
Copyright (C) 2013 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -17,13 +17,11 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_DIGEST_H__
#define __TINC_DIGEST_H__
#ifndef __TINC_OPENSSL_DIGEST_H__
#define __TINC_OPENSSL_DIGEST_H__
#include <openssl/evp.h>
#define DIGEST_MAX_SIZE EVP_MAX_MD_SIZE
typedef struct digest {
const EVP_MD *digest;
int maclength;
@ -31,16 +29,4 @@ typedef struct digest {
char *key;
} digest_t;
extern bool digest_open_by_name(struct digest *, const char *name, int maclength);
extern bool digest_open_by_nid(struct digest *, int nid, int maclength);
extern bool digest_open_sha1(struct digest *, int maclength);
extern void digest_close(struct digest *);
extern bool digest_create(struct digest *, const void *indata, size_t inlen, void *outdata);
extern bool digest_verify(struct digest *, const void *indata, size_t inlen, const void *digestdata);
extern bool digest_set_key(struct digest *, const void *key, size_t len);
extern int digest_get_nid(const struct digest *);
extern size_t digest_keylength(const struct digest *);
extern size_t digest_length(const struct digest *);
extern bool digest_active(const struct digest *);
#endif

View file

@ -1,6 +1,6 @@
/*
ecdh.c -- Diffie-Hellman key exchange handling
Copyright (C) 2011-2012 Guus Sliepen <guus@tinc-vpn.org>
Copyright (C) 2011-2013 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -17,68 +17,70 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "system.h"
#include "utils.h"
#include "xalloc.h"
#include "../system.h"
#include <openssl/err.h>
#include <openssl/ec.h>
#include <openssl/ecdh.h>
#include <openssl/obj_mac.h>
#include "ecdh.h"
#include "logger.h"
#define __TINC_ECDH_INTERNAL__
typedef EC_KEY ecdh_t;
bool ecdh_generate_public(ecdh_t *ecdh, void *pubkey) {
*ecdh = EC_KEY_new_by_curve_name(NID_secp521r1);
if(!*ecdh) {
#include "../ecdh.h"
#include "../logger.h"
#include "../utils.h"
#include "../xalloc.h"
ecdh_t *ecdh_generate_public(void *pubkey) {
ecdh_t *ecdh = EC_KEY_new_by_curve_name(NID_secp521r1);
if(!ecdh) {
logger(DEBUG_ALWAYS, LOG_ERR, "Generating EC key_by_curve_name failed: %s", ERR_error_string(ERR_get_error(), NULL));
return false;
}
if(!EC_KEY_generate_key(*ecdh)) {
EC_KEY_free(*ecdh);
*ecdh = NULL;
if(!EC_KEY_generate_key(ecdh)) {
EC_KEY_free(ecdh);
logger(DEBUG_ALWAYS, LOG_ERR, "Generating EC key failed: %s", ERR_error_string(ERR_get_error(), NULL));
return false;
return NULL;
}
const EC_POINT *point = EC_KEY_get0_public_key(*ecdh);
const EC_POINT *point = EC_KEY_get0_public_key(ecdh);
if(!point) {
EC_KEY_free(*ecdh);
*ecdh = NULL;
EC_KEY_free(ecdh);
logger(DEBUG_ALWAYS, LOG_ERR, "Getting public key failed: %s", ERR_error_string(ERR_get_error(), NULL));
return false;
return NULL;
}
size_t result = EC_POINT_point2oct(EC_KEY_get0_group(*ecdh), point, POINT_CONVERSION_COMPRESSED, pubkey, ECDH_SIZE, NULL);
size_t result = EC_POINT_point2oct(EC_KEY_get0_group(ecdh), point, POINT_CONVERSION_COMPRESSED, pubkey, ECDH_SIZE, NULL);
if(!result) {
EC_KEY_free(*ecdh);
*ecdh = NULL;
EC_KEY_free(ecdh);
logger(DEBUG_ALWAYS, LOG_ERR, "Converting EC_POINT to binary failed: %s", ERR_error_string(ERR_get_error(), NULL));
return false;
return NULL;
}
return true;
return ecdh;
}
bool ecdh_compute_shared(ecdh_t *ecdh, const void *pubkey, void *shared) {
EC_POINT *point = EC_POINT_new(EC_KEY_get0_group(*ecdh));
EC_POINT *point = EC_POINT_new(EC_KEY_get0_group(ecdh));
if(!point) {
logger(DEBUG_ALWAYS, LOG_ERR, "EC_POINT_new() failed: %s", ERR_error_string(ERR_get_error(), NULL));
EC_KEY_free(ecdh);
return false;
}
int result = EC_POINT_oct2point(EC_KEY_get0_group(*ecdh), point, pubkey, ECDH_SIZE, NULL);
int result = EC_POINT_oct2point(EC_KEY_get0_group(ecdh), point, pubkey, ECDH_SIZE, NULL);
if(!result) {
EC_POINT_free(point);
EC_KEY_free(ecdh);
logger(DEBUG_ALWAYS, LOG_ERR, "Converting binary to EC_POINT failed: %s", ERR_error_string(ERR_get_error(), NULL));
return false;
}
result = ECDH_compute_key(shared, ECDH_SIZE, point, *ecdh, NULL);
result = ECDH_compute_key(shared, ECDH_SIZE, point, ecdh, NULL);
EC_POINT_free(point);
EC_KEY_free(*ecdh);
*ecdh = NULL;
EC_KEY_free(ecdh);
if(!result) {
logger(DEBUG_ALWAYS, LOG_ERR, "Computing Elliptic Curve Diffie-Hellman shared key failed: %s", ERR_error_string(ERR_get_error(), NULL));
@ -89,8 +91,6 @@ bool ecdh_compute_shared(ecdh_t *ecdh, const void *pubkey, void *shared) {
}
void ecdh_free(ecdh_t *ecdh) {
if(*ecdh) {
EC_KEY_free(*ecdh);
*ecdh = NULL;
}
if(ecdh)
EC_KEY_free(ecdh);
}

View file

@ -1,34 +0,0 @@
/*
ecdh.h -- header file for ecdh.c
Copyright (C) 2011 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_ECDH_H__
#define __TINC_ECDH_H__
#include <openssl/ecdh.h>
#define ECDH_SIZE 67
#define ECDH_SHARED_SIZE 66
typedef EC_KEY *ecdh_t;
extern bool ecdh_generate_public(ecdh_t *ecdh, void *pubkey);
extern bool ecdh_compute_shared(ecdh_t *ecdh, const void *pubkey, void *shared);
extern void ecdh_free(ecdh_t *ecdh);
#endif

View file

@ -1,6 +1,6 @@
/*
ecdsa.c -- ECDSA key handling
Copyright (C) 2011-2012 Guus Sliepen <guus@tinc-vpn.org>
Copyright (C) 2011-2013 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -17,22 +17,26 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "system.h"
#include "../system.h"
#include <openssl/pem.h>
#include <openssl/err.h>
#include "logger.h"
#include "ecdsa.h"
#include "utils.h"
#define __TINC_ECDSA_INTERNAL__
typedef EC_KEY ecdsa_t;
#include "../logger.h"
#include "../ecdsa.h"
#include "../utils.h"
#include "../xalloc.h"
// Get and set ECDSA keys
//
bool ecdsa_set_base64_public_key(ecdsa_t *ecdsa, const char *p) {
*ecdsa = EC_KEY_new_by_curve_name(NID_secp521r1);
if(!*ecdsa) {
ecdsa_t *ecdsa_set_base64_public_key(const char *p) {
ecdsa_t *ecdsa = EC_KEY_new_by_curve_name(NID_secp521r1);
if(!ecdsa) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "EC_KEY_new_by_curve_name failed: %s", ERR_error_string(ERR_get_error(), NULL));
return false;
return NULL;
}
int len = strlen(p);
@ -40,19 +44,20 @@ bool ecdsa_set_base64_public_key(ecdsa_t *ecdsa, const char *p) {
const unsigned char *ppubkey = pubkey;
len = b64decode(p, (char *)pubkey, len);
if(!o2i_ECPublicKey(ecdsa, &ppubkey, len)) {
if(!o2i_ECPublicKey(&ecdsa, &ppubkey, len)) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "o2i_ECPublicKey failed: %s", ERR_error_string(ERR_get_error(), NULL));
return false;
EC_KEY_free(ecdsa);
return NULL;
}
return true;
return ecdsa;
}
char *ecdsa_get_base64_public_key(ecdsa_t *ecdsa) {
unsigned char *pubkey = NULL;
int len = i2o_ECPublicKey(*ecdsa, &pubkey);
int len = i2o_ECPublicKey(ecdsa, &pubkey);
char *base64 = malloc(len * 4 / 3 + 5);
char *base64 = xmalloc(len * 4 / 3 + 5);
b64encode((char *)pubkey, base64, len);
free(pubkey);
@ -62,41 +67,39 @@ char *ecdsa_get_base64_public_key(ecdsa_t *ecdsa) {
// Read PEM ECDSA keys
bool ecdsa_read_pem_public_key(ecdsa_t *ecdsa, FILE *fp) {
*ecdsa = PEM_read_EC_PUBKEY(fp, ecdsa, NULL, NULL);
ecdsa_t *ecdsa_read_pem_public_key(FILE *fp) {
ecdsa_t *ecdsa = PEM_read_EC_PUBKEY(fp, NULL, NULL, NULL);
if(*ecdsa)
return true;
if(!ecdsa)
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read ECDSA public key: %s", ERR_error_string(ERR_get_error(), NULL));
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read ECDSA public key: %s", ERR_error_string(ERR_get_error(), NULL));
return false;
return ecdsa;
}
bool ecdsa_read_pem_private_key(ecdsa_t *ecdsa, FILE *fp) {
*ecdsa = PEM_read_ECPrivateKey(fp, NULL, NULL, NULL);
ecdsa_t *ecdsa_read_pem_private_key(FILE *fp) {
ecdsa_t *ecdsa = PEM_read_ECPrivateKey(fp, NULL, NULL, NULL);
if(*ecdsa)
return true;
if(!ecdsa)
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read ECDSA private key: %s", ERR_error_string(ERR_get_error(), NULL));
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read ECDSA private key: %s", ERR_error_string(ERR_get_error(), NULL));
return false;
return ecdsa;
}
size_t ecdsa_size(ecdsa_t *ecdsa) {
return ECDSA_size(*ecdsa);
return ECDSA_size(ecdsa);
}
// TODO: standardise output format?
bool ecdsa_sign(ecdsa_t *ecdsa, const void *in, size_t len, void *sig) {
unsigned int siglen = ECDSA_size(*ecdsa);
unsigned int siglen = ECDSA_size(ecdsa);
unsigned char hash[SHA512_DIGEST_LENGTH];
SHA512(in, len, hash);
memset(sig, 0, siglen);
if(!ECDSA_sign(0, hash, sizeof hash, sig, &siglen, *ecdsa)) {
if(!ECDSA_sign(0, hash, sizeof hash, sig, &siglen, ecdsa)) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "ECDSA_sign() failed: %s", ERR_error_string(ERR_get_error(), NULL));
return false;
}
@ -105,12 +108,12 @@ bool ecdsa_sign(ecdsa_t *ecdsa, const void *in, size_t len, void *sig) {
}
bool ecdsa_verify(ecdsa_t *ecdsa, const void *in, size_t len, const void *sig) {
unsigned int siglen = ECDSA_size(*ecdsa);
unsigned int siglen = ECDSA_size(ecdsa);
unsigned char hash[SHA512_DIGEST_LENGTH];
SHA512(in, len, hash);
if(!ECDSA_verify(0, hash, sizeof hash, sig, siglen, *ecdsa)) {
if(!ECDSA_verify(0, hash, sizeof hash, sig, siglen, ecdsa)) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "ECDSA_verify() failed: %s", ERR_error_string(ERR_get_error(), NULL));
return false;
}
@ -119,12 +122,10 @@ bool ecdsa_verify(ecdsa_t *ecdsa, const void *in, size_t len, const void *sig) {
}
bool ecdsa_active(ecdsa_t *ecdsa) {
return *ecdsa;
return ecdsa;
}
void ecdsa_free(ecdsa_t *ecdsa) {
if(*ecdsa) {
EC_KEY_free(*ecdsa);
*ecdsa = NULL;
}
if(ecdsa)
EC_KEY_free(ecdsa);
}

View file

@ -1,37 +0,0 @@
/*
ecdsa.h -- ECDSA key handling
Copyright (C) 2011 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_ECDSA_H__
#define __TINC_ECDSA_H__
#include <openssl/ec.h>
typedef EC_KEY *ecdsa_t;
extern bool ecdsa_set_base64_public_key(ecdsa_t *ecdsa, const char *p);
extern char *ecdsa_get_base64_public_key(ecdsa_t *ecdsa);
extern bool ecdsa_read_pem_public_key(ecdsa_t *ecdsa, FILE *fp);
extern bool ecdsa_read_pem_private_key(ecdsa_t *ecdsa, FILE *fp);
extern size_t ecdsa_size(ecdsa_t *ecdsa);
extern bool ecdsa_sign(ecdsa_t *ecdsa, const void *in, size_t inlen, void *out);
extern bool ecdsa_verify(ecdsa_t *ecdsa, const void *in, size_t inlen, const void *out);
extern bool ecdsa_active(ecdsa_t *ecdsa);
extern void ecdsa_free(ecdsa_t *ecdsa);
#endif

View file

@ -1,6 +1,6 @@
/*
ecdsagen.c -- ECDSA key generation and export
Copyright (C) 2011 Guus Sliepen <guus@tinc-vpn.org>
Copyright (C) 2011-2013 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -17,59 +17,50 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "system.h"
#include "../system.h"
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/obj_mac.h>
#include "ecdsagen.h"
#include "utils.h"
#define __TINC_ECDSA_INTERNAL__
typedef EC_KEY ecdsa_t;
#include "../ecdsagen.h"
#include "../utils.h"
#include "../xalloc.h"
// Generate ECDSA key
bool ecdsa_generate(ecdsa_t *ecdsa) {
*ecdsa = EC_KEY_new_by_curve_name(NID_secp521r1);
ecdsa_t *ecdsa_generate(void) {
ecdsa_t *ecdsa = EC_KEY_new_by_curve_name(NID_secp521r1);
if(!EC_KEY_generate_key(*ecdsa)) {
if(!ecdsa || !EC_KEY_generate_key(ecdsa)) {
fprintf(stderr, "Generating EC key failed: %s", ERR_error_string(ERR_get_error(), NULL));
ecdsa_free(ecdsa);
return false;
}
EC_KEY_set_asn1_flag(*ecdsa, OPENSSL_EC_NAMED_CURVE);
EC_KEY_set_conv_form(*ecdsa, POINT_CONVERSION_COMPRESSED);
EC_KEY_set_asn1_flag(ecdsa, OPENSSL_EC_NAMED_CURVE);
EC_KEY_set_conv_form(ecdsa, POINT_CONVERSION_COMPRESSED);
return true;
return ecdsa;
}
// Write PEM ECDSA keys
bool ecdsa_write_pem_public_key(ecdsa_t *ecdsa, FILE *fp) {
BIO *out = BIO_new(BIO_s_file());
BIO_set_fp(out,fp,BIO_NOCLOSE);
PEM_write_bio_EC_PUBKEY(out, *ecdsa);
BIO_set_fp(out, fp, BIO_NOCLOSE);
PEM_write_bio_EC_PUBKEY(out, ecdsa);
BIO_free(out);
return true;
}
bool ecdsa_write_pem_private_key(ecdsa_t *ecdsa, FILE *fp) {
BIO *out = BIO_new(BIO_s_file());
BIO_set_fp(out,fp,BIO_NOCLOSE);
PEM_write_bio_ECPrivateKey(out, *ecdsa, NULL, NULL, 0, NULL, NULL);
BIO_set_fp(out, fp, BIO_NOCLOSE);
PEM_write_bio_ECPrivateKey(out, ecdsa, NULL, NULL, 0, NULL, NULL);
BIO_free(out);
return true;
}
// Convert ECDSA public key to base64 format
char *ecdsa_get_base64_public_key(ecdsa_t *ecdsa) {
unsigned char *pubkey = NULL;
int len = i2o_ECPublicKey(*ecdsa, &pubkey);
char *base64 = malloc(len * 4 / 3 + 5);
b64encode((char *)pubkey, base64, len);
free(pubkey);
return base64;
}

View file

@ -1,30 +0,0 @@
/*
ecdsagen.h -- ECDSA key generation and export
Copyright (C) 2011 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_ECDSAGEN_H__
#define __TINC_ECDSAGEN_H__
#include "ecdsa.h"
extern bool ecdsa_generate(ecdsa_t *ecdsa);
extern bool ecdsa_write_pem_public_key(ecdsa_t *ecdsa, FILE *fp);
extern bool ecdsa_write_pem_private_key(ecdsa_t *ecdsa, FILE *fp);
extern char *ecdsa_get_base64_public_key(ecdsa_t *ecdsa);
#endif

View file

@ -1,6 +1,6 @@
/*
prf.c -- Pseudo-Random Function for key material generation
Copyright (C) 2011-2012 Guus Sliepen <guus@tinc-vpn.org>
Copyright (C) 2011-2013 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -17,27 +17,30 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "system.h"
#include "../system.h"
#include <openssl/obj_mac.h>
#include "digest.h"
#include "prf.h"
#include "../digest.h"
#include "../prf.h"
/* Generate key material from a master secret and a seed, based on RFC 4346 section 5.
We use SHA512 instead of MD5 and SHA1.
*/
static bool prf_xor(int nid, const char *secret, size_t secretlen, char *seed, size_t seedlen, char *out, ssize_t outlen) {
digest_t digest;
digest_t *digest = digest_open_by_nid(nid, -1);
if(!digest_open_by_nid(&digest, nid, -1))
if(!digest)
return false;
if(!digest_set_key(&digest, secret, secretlen))
if(!digest_set_key(digest, secret, secretlen)) {
digest_close(digest);
return false;
}
size_t len = digest_length(&digest);
size_t len = digest_length(digest);
/* Data is what the "inner" HMAC function processes.
It consists of the previous HMAC result plus the seed.
@ -51,10 +54,10 @@ static bool prf_xor(int nid, const char *secret, size_t secretlen, char *seed, s
while(outlen > 0) {
/* Inner HMAC */
digest_create(&digest, data, len + seedlen, data);
digest_create(digest, data, len + seedlen, data);
/* Outer HMAC */
digest_create(&digest, data, len + seedlen, hash);
digest_create(digest, data, len + seedlen, hash);
/* XOR the results of the outer HMAC into the out buffer */
for(int i = 0; i < len && i < outlen; i++)
@ -63,7 +66,7 @@ static bool prf_xor(int nid, const char *secret, size_t secretlen, char *seed, s
outlen -= len;
}
digest_close(&digest);
digest_close(digest);
return true;
}

View file

@ -1,25 +0,0 @@
/*
prf.h -- header file for prf.c
Copyright (C) 2011 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_PRF_H__
#define __TINC_PRF_H__
extern bool prf(const char *secret, size_t secretlen, char *seed, size_t seedlen, char *out, size_t outlen);
#endif

View file

@ -1,6 +1,6 @@
/*
rsa.c -- RSA key handling
Copyright (C) 2007-2012 Guus Sliepen <guus@tinc-vpn.org>
Copyright (C) 2007-2013 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -17,69 +17,74 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "system.h"
#include "../system.h"
#include <openssl/pem.h>
#include <openssl/err.h>
#include "logger.h"
#include "rsa.h"
#define __TINC_RSA_INTERNAL__
typedef RSA rsa_t;
#include "../logger.h"
#include "../rsa.h"
// Set RSA keys
bool rsa_set_hex_public_key(rsa_t *rsa, char *n, char *e) {
*rsa = RSA_new();
if(BN_hex2bn(&(*rsa)->n, n) != strlen(n))
rsa_t *rsa_set_hex_public_key(char *n, char *e) {
rsa_t *rsa = RSA_new();
if(!rsa)
return NULL;
if(BN_hex2bn(&rsa->n, n) != strlen(n) || BN_hex2bn(&rsa->e, e) != strlen(e)) {
RSA_free(rsa);
return false;
if(BN_hex2bn(&(*rsa)->e, e) != strlen(e))
return false;
return true;
}
return rsa;
}
bool rsa_set_hex_private_key(rsa_t *rsa, char *n, char *e, char *d) {
*rsa = RSA_new();
if(BN_hex2bn(&(*rsa)->n, n) != strlen(n))
rsa_t *rsa_set_hex_private_key(char *n, char *e, char *d) {
rsa_t *rsa = RSA_new();
if(!rsa)
return NULL;
if(BN_hex2bn(&rsa->n, n) != strlen(n) || BN_hex2bn(&rsa->e, e) != strlen(e) || BN_hex2bn(&rsa->d, d) != strlen(d)) {
RSA_free(rsa);
return false;
if(BN_hex2bn(&(*rsa)->e, e) != strlen(e))
return false;
if(BN_hex2bn(&(*rsa)->d, d) != strlen(d))
return false;
return true;
}
return rsa;
}
// Read PEM RSA keys
bool rsa_read_pem_public_key(rsa_t *rsa, FILE *fp) {
*rsa = PEM_read_RSAPublicKey(fp, rsa, NULL, NULL);
rsa_t *rsa_read_pem_public_key(FILE *fp) {
rsa_t *rsa = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL);
if(*rsa)
return true;
if(!rsa)
rsa = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL);
*rsa = PEM_read_RSA_PUBKEY(fp, rsa, NULL, NULL);
if(!rsa)
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read RSA public key: %s", ERR_error_string(ERR_get_error(), NULL));
if(*rsa)
return true;
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read RSA public key: %s", ERR_error_string(ERR_get_error(), NULL));
return false;
return rsa;
}
bool rsa_read_pem_private_key(rsa_t *rsa, FILE *fp) {
*rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
rsa_t *rsa_read_pem_private_key(FILE *fp) {
rsa_t *rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
if(*rsa)
return true;
if(!rsa)
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read RSA private key: %s", ERR_error_string(ERR_get_error(), NULL));
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read RSA private key: %s", ERR_error_string(ERR_get_error(), NULL));
return false;
return rsa;
}
size_t rsa_size(rsa_t *rsa) {
return RSA_size(*rsa);
return RSA_size(rsa);
}
bool rsa_public_encrypt(rsa_t *rsa, void *in, size_t len, void *out) {
if(RSA_public_encrypt(len, in, out, *rsa, RSA_NO_PADDING) == len)
if(RSA_public_encrypt(len, in, out, rsa, RSA_NO_PADDING) == len)
return true;
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to perform RSA encryption: %s", ERR_error_string(ERR_get_error(), NULL));
@ -87,7 +92,7 @@ bool rsa_public_encrypt(rsa_t *rsa, void *in, size_t len, void *out) {
}
bool rsa_private_decrypt(rsa_t *rsa, void *in, size_t len, void *out) {
if(RSA_private_decrypt(len, in, out, *rsa, RSA_NO_PADDING) == len)
if(RSA_private_decrypt(len, in, out, rsa, RSA_NO_PADDING) == len)
return true;
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to perform RSA decryption: %s", ERR_error_string(ERR_get_error(), NULL));
@ -95,12 +100,10 @@ bool rsa_private_decrypt(rsa_t *rsa, void *in, size_t len, void *out) {
}
bool rsa_active(rsa_t *rsa) {
return *rsa;
return rsa;
}
void rsa_free(rsa_t *rsa) {
if(*rsa) {
RSA_free(*rsa);
*rsa = NULL;
}
if(rsa)
RSA_free(rsa);
}

View file

@ -1,38 +0,0 @@
/*
rsa.h -- RSA key handling
Copyright (C) 2007-2011 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_RSA_H__
#define __TINC_RSA_H__
#include <openssl/rsa.h>
typedef RSA *rsa_t;
extern bool rsa_set_hex_public_key(rsa_t *rsa, char *n, char *e);
extern bool rsa_set_hex_private_key(rsa_t *rsa, char *n, char *e, char *d);
extern bool rsa_read_pem_public_key(rsa_t *rsa, FILE *fp);
extern bool rsa_read_pem_private_key(rsa_t *rsa, FILE *fp);
extern size_t rsa_size(rsa_t *rsa);
extern bool rsa_public_encrypt(rsa_t *rsa, void *in, size_t inlen, void *out);
extern bool rsa_private_decrypt(rsa_t *rsa, void *in, size_t inlen, void *out);
extern bool rsa_active(rsa_t *rsa);
extern void rsa_free(rsa_t *rsa);
#endif

View file

@ -1,6 +1,6 @@
/*
rsagen.c -- RSA key generation and export
Copyright (C) 2008 Guus Sliepen <guus@tinc-vpn.org>
Copyright (C) 2008-2013 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -17,13 +17,16 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "system.h"
#include "../system.h"
#include <openssl/pem.h>
#include <openssl/err.h>
#include "logger.h"
#include "rsagen.h"
#define __TINC_RSA_INTERNAL__
typedef RSA rsa_t;
#include "../logger.h"
#include "../rsagen.h"
/* This function prettyprints the key generation process */
@ -63,21 +66,16 @@ static void indicator(int a, int b, void *p) {
// Generate RSA key
bool rsa_generate(rsa_t *rsa, size_t bits, unsigned long exponent) {
*rsa = RSA_generate_key(bits, exponent, indicator, NULL);
return *rsa;
rsa_t *rsa_generate(size_t bits, unsigned long exponent) {
return RSA_generate_key(bits, exponent, indicator, NULL);
}
// Write PEM RSA keys
bool rsa_write_pem_public_key(rsa_t *rsa, FILE *fp) {
PEM_write_RSAPublicKey(fp, *rsa);
return true;
return PEM_write_RSAPublicKey(fp, rsa);
}
bool rsa_write_pem_private_key(rsa_t *rsa, FILE *fp) {
PEM_write_RSAPrivateKey(fp, *rsa, NULL, NULL, 0, NULL, NULL);
return true;
return PEM_write_RSAPrivateKey(fp, rsa, NULL, NULL, 0, NULL, NULL);
}

View file

@ -1,29 +0,0 @@
/*
rsagen.h -- RSA key generation and export
Copyright (C) 2008 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_RSAGEN_H__
#define __TINC_RSAGEN_H__
#include "rsa.h"
extern bool rsa_generate(rsa_t *rsa, size_t bits, unsigned long exponent);
extern bool rsa_write_pem_public_key(rsa_t *rsa, FILE *fp);
extern bool rsa_write_pem_private_key(rsa_t *rsa, FILE *fp);
#endif