Merge branch 'openssl-1.1.0'
This adds support for OpenSSL 1.1.0. Several APIs have changed and it makes all types opaque, which requires using new getter/setter functions. For older versions fallbacks are provided.
This commit is contained in:
@@ -46,6 +46,17 @@
|
|||||||
#include <collections/enumerator.h>
|
#include <collections/enumerator.h>
|
||||||
#include <credentials/certificates/x509.h>
|
#include <credentials/certificates/x509.h>
|
||||||
|
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
|
static inline void X509_CRL_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg, const X509_CRL *crl) {
|
||||||
|
if (psig) { *psig = crl->signature; }
|
||||||
|
if (palg) { *palg = crl->sig_alg; }
|
||||||
|
}
|
||||||
|
#define X509_REVOKED_get0_serialNumber(r) ({ (r)->serialNumber; })
|
||||||
|
#define X509_REVOKED_get0_revocationDate(r) ({ (r)->revocationDate; })
|
||||||
|
#define X509_CRL_get0_extensions(c) ({ (c)->crl->extensions; })
|
||||||
|
#define X509_ALGOR_get0(oid, ppt, ppv, alg) ({ *(oid) = (alg)->algorithm; })
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct private_openssl_crl_t private_openssl_crl_t;
|
typedef struct private_openssl_crl_t private_openssl_crl_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -141,11 +152,13 @@ METHOD(enumerator_t, crl_enumerate, bool,
|
|||||||
revoked = sk_X509_REVOKED_value(this->stack, this->i);
|
revoked = sk_X509_REVOKED_value(this->stack, this->i);
|
||||||
if (serial)
|
if (serial)
|
||||||
{
|
{
|
||||||
*serial = openssl_asn1_str2chunk(revoked->serialNumber);
|
*serial = openssl_asn1_str2chunk(
|
||||||
|
X509_REVOKED_get0_serialNumber(revoked));
|
||||||
}
|
}
|
||||||
if (date)
|
if (date)
|
||||||
{
|
{
|
||||||
*date = openssl_asn1_to_time(revoked->revocationDate);
|
*date = openssl_asn1_to_time(
|
||||||
|
X509_REVOKED_get0_revocationDate(revoked));
|
||||||
}
|
}
|
||||||
if (reason)
|
if (reason)
|
||||||
{
|
{
|
||||||
@@ -231,6 +244,7 @@ METHOD(certificate_t, issued_by, bool,
|
|||||||
chunk_t fingerprint, tbs;
|
chunk_t fingerprint, tbs;
|
||||||
public_key_t *key;
|
public_key_t *key;
|
||||||
x509_t *x509;
|
x509_t *x509;
|
||||||
|
ASN1_BIT_STRING *sig;
|
||||||
bool valid;
|
bool valid;
|
||||||
|
|
||||||
if (issuer->get_type(issuer) != CERT_X509)
|
if (issuer->get_type(issuer) != CERT_X509)
|
||||||
@@ -266,9 +280,14 @@ METHOD(certificate_t, issued_by, bool,
|
|||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
/* i2d_re_X509_CRL_tbs() was added with 1.1.0 when X509_CRL became opaque */
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||||
|
tbs = openssl_i2chunk(re_X509_CRL_tbs, this->crl);
|
||||||
|
#else
|
||||||
tbs = openssl_i2chunk(X509_CRL_INFO, this->crl->crl);
|
tbs = openssl_i2chunk(X509_CRL_INFO, this->crl->crl);
|
||||||
valid = key->verify(key, this->scheme, tbs,
|
#endif
|
||||||
openssl_asn1_str2chunk(this->crl->signature));
|
X509_CRL_get0_signature(&sig, NULL, this->crl);
|
||||||
|
valid = key->verify(key, this->scheme, tbs, openssl_asn1_str2chunk(sig));
|
||||||
free(tbs.ptr);
|
free(tbs.ptr);
|
||||||
key->destroy(key);
|
key->destroy(key);
|
||||||
if (valid && scheme)
|
if (valid && scheme)
|
||||||
@@ -448,7 +467,7 @@ static bool parse_extensions(private_openssl_crl_t *this)
|
|||||||
X509_EXTENSION *ext;
|
X509_EXTENSION *ext;
|
||||||
STACK_OF(X509_EXTENSION) *extensions;
|
STACK_OF(X509_EXTENSION) *extensions;
|
||||||
|
|
||||||
extensions = this->crl->crl->extensions;
|
extensions = X509_CRL_get0_extensions(this->crl);
|
||||||
if (extensions)
|
if (extensions)
|
||||||
{
|
{
|
||||||
num = sk_X509_EXTENSION_num(extensions);
|
num = sk_X509_EXTENSION_num(extensions);
|
||||||
@@ -494,6 +513,8 @@ static bool parse_extensions(private_openssl_crl_t *this)
|
|||||||
static bool parse_crl(private_openssl_crl_t *this)
|
static bool parse_crl(private_openssl_crl_t *this)
|
||||||
{
|
{
|
||||||
const unsigned char *ptr = this->encoding.ptr;
|
const unsigned char *ptr = this->encoding.ptr;
|
||||||
|
ASN1_OBJECT *oid;
|
||||||
|
X509_ALGOR *alg;
|
||||||
|
|
||||||
this->crl = d2i_X509_CRL(NULL, &ptr, this->encoding.len);
|
this->crl = d2i_X509_CRL(NULL, &ptr, this->encoding.len);
|
||||||
if (!this->crl)
|
if (!this->crl)
|
||||||
@@ -501,14 +522,28 @@ static bool parse_crl(private_openssl_crl_t *this)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
X509_CRL_get0_signature(NULL, &alg, this->crl);
|
||||||
|
X509_ALGOR_get0(&oid, NULL, NULL, alg);
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
if (!chunk_equals(
|
if (!chunk_equals(
|
||||||
openssl_asn1_obj2chunk(this->crl->crl->sig_alg->algorithm),
|
openssl_asn1_obj2chunk(this->crl->crl->sig_alg->algorithm),
|
||||||
openssl_asn1_obj2chunk(this->crl->sig_alg->algorithm)))
|
openssl_asn1_obj2chunk(this->crl->sig_alg->algorithm)))
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
this->scheme = signature_scheme_from_oid(openssl_asn1_known_oid(
|
#elif 0
|
||||||
this->crl->sig_alg->algorithm));
|
/* FIXME: we currently can't do this if X509_CRL is opaque (>= 1.1.0) as
|
||||||
|
* X509_CRL_get0_tbs_sigalg() does not exist and there does not seem to be
|
||||||
|
* another easy way to get the algorithm from the tbsCertList of the CRL */
|
||||||
|
alg = X509_CRL_get0_tbs_sigalg(this->crl);
|
||||||
|
X509_ALGOR_get0(&oid_tbs, NULL, NULL, alg);
|
||||||
|
if (!chunk_equals(openssl_asn1_obj2chunk(oid),
|
||||||
|
openssl_asn1_obj2chunk(oid_tbs)))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
this->scheme = signature_scheme_from_oid(openssl_asn1_known_oid(oid));
|
||||||
|
|
||||||
this->issuer = openssl_x509_name2id(X509_CRL_get_issuer(this->crl));
|
this->issuer = openssl_x509_name2id(X509_CRL_get_issuer(this->crl));
|
||||||
if (!this->issuer)
|
if (!this->issuer)
|
||||||
|
|||||||
@@ -93,8 +93,10 @@ static char* lookup_algorithm(uint16_t ikev2_algo, size_t *key_size)
|
|||||||
static bool crypt(private_openssl_crypter_t *this, chunk_t data, chunk_t iv,
|
static bool crypt(private_openssl_crypter_t *this, chunk_t data, chunk_t iv,
|
||||||
chunk_t *dst, int enc)
|
chunk_t *dst, int enc)
|
||||||
{
|
{
|
||||||
|
EVP_CIPHER_CTX *ctx;
|
||||||
int len;
|
int len;
|
||||||
u_char *out;
|
u_char *out;
|
||||||
|
bool success = FALSE;
|
||||||
|
|
||||||
out = data.ptr;
|
out = data.ptr;
|
||||||
if (dst)
|
if (dst)
|
||||||
@@ -102,16 +104,19 @@ static bool crypt(private_openssl_crypter_t *this, chunk_t data, chunk_t iv,
|
|||||||
*dst = chunk_alloc(data.len);
|
*dst = chunk_alloc(data.len);
|
||||||
out = dst->ptr;
|
out = dst->ptr;
|
||||||
}
|
}
|
||||||
EVP_CIPHER_CTX ctx;
|
ctx = EVP_CIPHER_CTX_new();
|
||||||
EVP_CIPHER_CTX_init(&ctx);
|
if (EVP_CipherInit_ex(ctx, this->cipher, NULL, NULL, NULL, enc) &&
|
||||||
return EVP_CipherInit_ex(&ctx, this->cipher, NULL, NULL, NULL, enc) &&
|
EVP_CIPHER_CTX_set_padding(ctx, 0) /* disable padding */ &&
|
||||||
EVP_CIPHER_CTX_set_padding(&ctx, 0) /* disable padding */ &&
|
EVP_CIPHER_CTX_set_key_length(ctx, this->key.len) &&
|
||||||
EVP_CIPHER_CTX_set_key_length(&ctx, this->key.len) &&
|
EVP_CipherInit_ex(ctx, NULL, NULL, this->key.ptr, iv.ptr, enc) &&
|
||||||
EVP_CipherInit_ex(&ctx, NULL, NULL, this->key.ptr, iv.ptr, enc) &&
|
EVP_CipherUpdate(ctx, out, &len, data.ptr, data.len) &&
|
||||||
EVP_CipherUpdate(&ctx, out, &len, data.ptr, data.len) &&
|
|
||||||
/* since padding is disabled this does nothing */
|
/* since padding is disabled this does nothing */
|
||||||
EVP_CipherFinal_ex(&ctx, out + len, &len) &&
|
EVP_CipherFinal_ex(ctx, out + len, &len))
|
||||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
{
|
||||||
|
success = TRUE;
|
||||||
|
}
|
||||||
|
EVP_CIPHER_CTX_free(ctx);
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(crypter_t, decrypt, bool,
|
METHOD(crypter_t, decrypt, bool,
|
||||||
@@ -129,13 +134,13 @@ METHOD(crypter_t, encrypt, bool,
|
|||||||
METHOD(crypter_t, get_block_size, size_t,
|
METHOD(crypter_t, get_block_size, size_t,
|
||||||
private_openssl_crypter_t *this)
|
private_openssl_crypter_t *this)
|
||||||
{
|
{
|
||||||
return this->cipher->block_size;
|
return EVP_CIPHER_block_size(this->cipher);
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(crypter_t, get_iv_size, size_t,
|
METHOD(crypter_t, get_iv_size, size_t,
|
||||||
private_openssl_crypter_t *this)
|
private_openssl_crypter_t *this)
|
||||||
{
|
{
|
||||||
return this->cipher->iv_len;
|
return EVP_CIPHER_iv_length(this->cipher);
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(crypter_t, get_key_size, size_t,
|
METHOD(crypter_t, get_key_size, size_t,
|
||||||
|
|||||||
@@ -22,9 +22,17 @@
|
|||||||
#include <openssl/dh.h>
|
#include <openssl/dh.h>
|
||||||
|
|
||||||
#include "openssl_diffie_hellman.h"
|
#include "openssl_diffie_hellman.h"
|
||||||
|
#include "openssl_util.h"
|
||||||
|
|
||||||
#include <utils/debug.h>
|
#include <utils/debug.h>
|
||||||
|
|
||||||
|
/* these were added with 1.1.0 when DH was made opaque */
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
|
OPENSSL_KEY_FALLBACK(DH, key, pub_key, priv_key)
|
||||||
|
OPENSSL_KEY_FALLBACK(DH, pqg, p, q, g)
|
||||||
|
#define DH_set_length(dh, len) ({ (dh)->length = len; 1; })
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct private_openssl_diffie_hellman_t private_openssl_diffie_hellman_t;
|
typedef struct private_openssl_diffie_hellman_t private_openssl_diffie_hellman_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,10 +73,12 @@ struct private_openssl_diffie_hellman_t {
|
|||||||
METHOD(diffie_hellman_t, get_my_public_value, bool,
|
METHOD(diffie_hellman_t, get_my_public_value, bool,
|
||||||
private_openssl_diffie_hellman_t *this, chunk_t *value)
|
private_openssl_diffie_hellman_t *this, chunk_t *value)
|
||||||
{
|
{
|
||||||
|
const BIGNUM *pubkey;
|
||||||
|
|
||||||
*value = chunk_alloc(DH_size(this->dh));
|
*value = chunk_alloc(DH_size(this->dh));
|
||||||
memset(value->ptr, 0, value->len);
|
memset(value->ptr, 0, value->len);
|
||||||
BN_bn2bin(this->dh->pub_key,
|
DH_get0_key(this->dh, &pubkey, NULL);
|
||||||
value->ptr + value->len - BN_num_bytes(this->dh->pub_key));
|
BN_bn2bin(pubkey, value->ptr + value->len - BN_num_bytes(pubkey));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,8 +126,15 @@ METHOD(diffie_hellman_t, set_other_public_value, bool,
|
|||||||
METHOD(diffie_hellman_t, set_private_value, bool,
|
METHOD(diffie_hellman_t, set_private_value, bool,
|
||||||
private_openssl_diffie_hellman_t *this, chunk_t value)
|
private_openssl_diffie_hellman_t *this, chunk_t value)
|
||||||
{
|
{
|
||||||
if (BN_bin2bn(value.ptr, value.len, this->dh->priv_key))
|
BIGNUM *privkey;
|
||||||
|
|
||||||
|
privkey = BN_bin2bn(value.ptr, value.len, NULL);
|
||||||
|
if (privkey)
|
||||||
{
|
{
|
||||||
|
if (!DH_set0_key(this->dh, NULL, privkey))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
chunk_clear(&this->shared_secret);
|
chunk_clear(&this->shared_secret);
|
||||||
this->computed = FALSE;
|
this->computed = FALSE;
|
||||||
return DH_generate_key(this->dh);
|
return DH_generate_key(this->dh);
|
||||||
@@ -136,19 +153,28 @@ METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
|
|||||||
*/
|
*/
|
||||||
static status_t set_modulus(private_openssl_diffie_hellman_t *this)
|
static status_t set_modulus(private_openssl_diffie_hellman_t *this)
|
||||||
{
|
{
|
||||||
|
BIGNUM *p, *g;
|
||||||
|
|
||||||
diffie_hellman_params_t *params = diffie_hellman_get_params(this->group);
|
diffie_hellman_params_t *params = diffie_hellman_get_params(this->group);
|
||||||
if (!params)
|
if (!params)
|
||||||
{
|
{
|
||||||
return NOT_FOUND;
|
return NOT_FOUND;
|
||||||
}
|
}
|
||||||
this->dh->p = BN_bin2bn(params->prime.ptr, params->prime.len, NULL);
|
p = BN_bin2bn(params->prime.ptr, params->prime.len, NULL);
|
||||||
this->dh->g = BN_bin2bn(params->generator.ptr, params->generator.len, NULL);
|
g = BN_bin2bn(params->generator.ptr, params->generator.len, NULL);
|
||||||
|
if (!DH_set0_pqg(this->dh, p, NULL, g))
|
||||||
|
{
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
if (params->exp_len != params->prime.len)
|
if (params->exp_len != params->prime.len)
|
||||||
{
|
{
|
||||||
#ifdef OPENSSL_IS_BORINGSSL
|
#ifdef OPENSSL_IS_BORINGSSL
|
||||||
this->dh->priv_length = params->exp_len * 8;
|
this->dh->priv_length = params->exp_len * 8;
|
||||||
#else
|
#else
|
||||||
this->dh->length = params->exp_len * 8;
|
if (!DH_set_length(this->dh, params->exp_len * 8))
|
||||||
|
{
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
@@ -170,6 +196,7 @@ openssl_diffie_hellman_t *openssl_diffie_hellman_create(
|
|||||||
diffie_hellman_group_t group, chunk_t g, chunk_t p)
|
diffie_hellman_group_t group, chunk_t g, chunk_t p)
|
||||||
{
|
{
|
||||||
private_openssl_diffie_hellman_t *this;
|
private_openssl_diffie_hellman_t *this;
|
||||||
|
const BIGNUM *privkey;
|
||||||
|
|
||||||
INIT(this,
|
INIT(this,
|
||||||
.public = {
|
.public = {
|
||||||
@@ -198,8 +225,12 @@ openssl_diffie_hellman_t *openssl_diffie_hellman_create(
|
|||||||
|
|
||||||
if (group == MODP_CUSTOM)
|
if (group == MODP_CUSTOM)
|
||||||
{
|
{
|
||||||
this->dh->p = BN_bin2bn(p.ptr, p.len, NULL);
|
if (!DH_set0_pqg(this->dh, BN_bin2bn(p.ptr, p.len, NULL), NULL,
|
||||||
this->dh->g = BN_bin2bn(g.ptr, g.len, NULL);
|
BN_bin2bn(g.ptr, g.len, NULL)))
|
||||||
|
{
|
||||||
|
destroy(this);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -217,9 +248,8 @@ openssl_diffie_hellman_t *openssl_diffie_hellman_create(
|
|||||||
destroy(this);
|
destroy(this);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
DBG2(DBG_LIB, "size of DH secret exponent: %d bits",
|
DH_get0_key(this->dh, NULL, &privkey);
|
||||||
BN_num_bits(this->dh->priv_key));
|
DBG2(DBG_LIB, "size of DH secret exponent: %d bits", BN_num_bits(privkey));
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,10 @@
|
|||||||
#include <openssl/ecdsa.h>
|
#include <openssl/ecdsa.h>
|
||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
|
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
|
OPENSSL_KEY_FALLBACK(ECDSA_SIG, r, s)
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct private_openssl_ec_private_key_t private_openssl_ec_private_key_t;
|
typedef struct private_openssl_ec_private_key_t private_openssl_ec_private_key_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -59,15 +63,17 @@ bool openssl_ec_fingerprint(EC_KEY *ec, cred_encoding_type_t type, chunk_t *fp);
|
|||||||
static bool build_signature(private_openssl_ec_private_key_t *this,
|
static bool build_signature(private_openssl_ec_private_key_t *this,
|
||||||
chunk_t hash, chunk_t *signature)
|
chunk_t hash, chunk_t *signature)
|
||||||
{
|
{
|
||||||
bool built = FALSE;
|
const BIGNUM *r, *s;
|
||||||
ECDSA_SIG *sig;
|
ECDSA_SIG *sig;
|
||||||
|
bool built = FALSE;
|
||||||
|
|
||||||
sig = ECDSA_do_sign(hash.ptr, hash.len, this->ec);
|
sig = ECDSA_do_sign(hash.ptr, hash.len, this->ec);
|
||||||
if (sig)
|
if (sig)
|
||||||
{
|
{
|
||||||
|
ECDSA_SIG_get0(sig, &r, &s);
|
||||||
/* concatenate BNs r/s to a signature chunk */
|
/* concatenate BNs r/s to a signature chunk */
|
||||||
built = openssl_bn_cat(EC_FIELD_ELEMENT_LEN(EC_KEY_get0_group(this->ec)),
|
built = openssl_bn_cat(EC_FIELD_ELEMENT_LEN(EC_KEY_get0_group(this->ec)),
|
||||||
sig->r, sig->s, signature);
|
r, s, signature);
|
||||||
ECDSA_SIG_free(sig);
|
ECDSA_SIG_free(sig);
|
||||||
}
|
}
|
||||||
return built;
|
return built;
|
||||||
|
|||||||
@@ -27,6 +27,10 @@
|
|||||||
#include <openssl/ecdsa.h>
|
#include <openssl/ecdsa.h>
|
||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
|
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
|
OPENSSL_KEY_FALLBACK(ECDSA_SIG, r, s)
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct private_openssl_ec_public_key_t private_openssl_ec_public_key_t;
|
typedef struct private_openssl_ec_public_key_t private_openssl_ec_public_key_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -55,14 +59,23 @@ struct private_openssl_ec_public_key_t {
|
|||||||
static bool verify_signature(private_openssl_ec_public_key_t *this,
|
static bool verify_signature(private_openssl_ec_public_key_t *this,
|
||||||
chunk_t hash, chunk_t signature)
|
chunk_t hash, chunk_t signature)
|
||||||
{
|
{
|
||||||
bool valid = FALSE;
|
BIGNUM *r, *s;
|
||||||
ECDSA_SIG *sig;
|
ECDSA_SIG *sig;
|
||||||
|
bool valid = FALSE;
|
||||||
|
|
||||||
sig = ECDSA_SIG_new();
|
sig = ECDSA_SIG_new();
|
||||||
if (sig)
|
if (sig)
|
||||||
{
|
{
|
||||||
/* split the signature chunk in r and s */
|
r = BN_new();
|
||||||
if (openssl_bn_split(signature, sig->r, sig->s))
|
s = BN_new();
|
||||||
|
if (!openssl_bn_split(signature, r, s))
|
||||||
|
{
|
||||||
|
BN_free(r);
|
||||||
|
BN_free(s);
|
||||||
|
ECDSA_SIG_free(sig);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (ECDSA_SIG_set0(sig, r, s))
|
||||||
{
|
{
|
||||||
valid = (ECDSA_do_verify(hash.ptr, hash.len, sig, this->ec) == 1);
|
valid = (ECDSA_do_verify(hash.ptr, hash.len, sig, this->ec) == 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ struct private_aead_t {
|
|||||||
static bool crypt(private_aead_t *this, chunk_t data, chunk_t assoc, chunk_t iv,
|
static bool crypt(private_aead_t *this, chunk_t data, chunk_t assoc, chunk_t iv,
|
||||||
u_char *out, int enc)
|
u_char *out, int enc)
|
||||||
{
|
{
|
||||||
EVP_CIPHER_CTX ctx;
|
EVP_CIPHER_CTX *ctx;
|
||||||
u_char nonce[NONCE_LEN];
|
u_char nonce[NONCE_LEN];
|
||||||
bool success = FALSE;
|
bool success = FALSE;
|
||||||
int len;
|
int len;
|
||||||
@@ -79,29 +79,29 @@ static bool crypt(private_aead_t *this, chunk_t data, chunk_t assoc, chunk_t iv,
|
|||||||
memcpy(nonce, this->salt, SALT_LEN);
|
memcpy(nonce, this->salt, SALT_LEN);
|
||||||
memcpy(nonce + SALT_LEN, iv.ptr, IV_LEN);
|
memcpy(nonce + SALT_LEN, iv.ptr, IV_LEN);
|
||||||
|
|
||||||
EVP_CIPHER_CTX_init(&ctx);
|
ctx = EVP_CIPHER_CTX_new();
|
||||||
EVP_CIPHER_CTX_set_padding(&ctx, 0);
|
EVP_CIPHER_CTX_set_padding(ctx, 0);
|
||||||
if (!EVP_CipherInit_ex(&ctx, this->cipher, NULL, NULL, NULL, enc) ||
|
if (!EVP_CipherInit_ex(ctx, this->cipher, NULL, NULL, NULL, enc) ||
|
||||||
!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, NONCE_LEN, NULL) ||
|
!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, NONCE_LEN, NULL) ||
|
||||||
!EVP_CipherInit_ex(&ctx, NULL, NULL, this->key.ptr, nonce, enc))
|
!EVP_CipherInit_ex(ctx, NULL, NULL, this->key.ptr, nonce, enc))
|
||||||
{
|
{
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (!enc && !EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_TAG, this->icv_size,
|
if (!enc && !EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, this->icv_size,
|
||||||
data.ptr + data.len))
|
data.ptr + data.len))
|
||||||
{ /* set ICV for verification on decryption */
|
{ /* set ICV for verification on decryption */
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (assoc.len && !EVP_CipherUpdate(&ctx, NULL, &len, assoc.ptr, assoc.len))
|
if (assoc.len && !EVP_CipherUpdate(ctx, NULL, &len, assoc.ptr, assoc.len))
|
||||||
{ /* set AAD if specified */
|
{ /* set AAD if specified */
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (!EVP_CipherUpdate(&ctx, out, &len, data.ptr, data.len) ||
|
if (!EVP_CipherUpdate(ctx, out, &len, data.ptr, data.len) ||
|
||||||
!EVP_CipherFinal_ex(&ctx, out + len, &len))
|
!EVP_CipherFinal_ex(ctx, out + len, &len))
|
||||||
{ /* EVP_CipherFinal_ex fails if ICV is incorrect on decryption */
|
{ /* EVP_CipherFinal_ex fails if ICV is incorrect on decryption */
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (enc && !EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, this->icv_size,
|
if (enc && !EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, this->icv_size,
|
||||||
out + data.len))
|
out + data.len))
|
||||||
{ /* copy back the ICV when encrypting */
|
{ /* copy back the ICV when encrypting */
|
||||||
goto done;
|
goto done;
|
||||||
@@ -109,7 +109,7 @@ static bool crypt(private_aead_t *this, chunk_t data, chunk_t assoc, chunk_t iv,
|
|||||||
success = TRUE;
|
success = TRUE;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
EVP_CIPHER_CTX_free(ctx);
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,7 +152,7 @@ METHOD(aead_t, decrypt, bool,
|
|||||||
METHOD(aead_t, get_block_size, size_t,
|
METHOD(aead_t, get_block_size, size_t,
|
||||||
private_aead_t *this)
|
private_aead_t *this)
|
||||||
{
|
{
|
||||||
return this->cipher->block_size;
|
return EVP_CIPHER_block_size(this->cipher);
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(aead_t, get_icv_size, size_t,
|
METHOD(aead_t, get_icv_size, size_t,
|
||||||
|
|||||||
@@ -68,7 +68,14 @@ struct private_mac_t {
|
|||||||
/**
|
/**
|
||||||
* Current HMAC context
|
* Current HMAC context
|
||||||
*/
|
*/
|
||||||
HMAC_CTX hmac;
|
HMAC_CTX *hmac;
|
||||||
|
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
|
/**
|
||||||
|
* Static context for OpenSSL < 1.1.0
|
||||||
|
*/
|
||||||
|
HMAC_CTX hmac_ctx;
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key set on HMAC_CTX?
|
* Key set on HMAC_CTX?
|
||||||
@@ -80,14 +87,14 @@ METHOD(mac_t, set_key, bool,
|
|||||||
private_mac_t *this, chunk_t key)
|
private_mac_t *this, chunk_t key)
|
||||||
{
|
{
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||||||
if (HMAC_Init_ex(&this->hmac, key.ptr, key.len, this->hasher, NULL))
|
if (HMAC_Init_ex(this->hmac, key.ptr, key.len, this->hasher, NULL))
|
||||||
{
|
{
|
||||||
this->key_set = TRUE;
|
this->key_set = TRUE;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
#else /* OPENSSL_VERSION_NUMBER < 1.0 */
|
#else /* OPENSSL_VERSION_NUMBER < 1.0 */
|
||||||
HMAC_Init_ex(&this->hmac, key.ptr, key.len, this->hasher, NULL);
|
HMAC_Init_ex(this->hmac, key.ptr, key.len, this->hasher, NULL);
|
||||||
this->key_set = TRUE;
|
this->key_set = TRUE;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
#endif
|
#endif
|
||||||
@@ -101,7 +108,7 @@ METHOD(mac_t, get_mac, bool,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||||||
if (!HMAC_Update(&this->hmac, data.ptr, data.len))
|
if (!HMAC_Update(this->hmac, data.ptr, data.len))
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@@ -109,17 +116,17 @@ METHOD(mac_t, get_mac, bool,
|
|||||||
{
|
{
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
if (!HMAC_Final(&this->hmac, out, NULL))
|
if (!HMAC_Final(this->hmac, out, NULL))
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
#else /* OPENSSL_VERSION_NUMBER < 1.0 */
|
#else /* OPENSSL_VERSION_NUMBER < 1.0 */
|
||||||
HMAC_Update(&this->hmac, data.ptr, data.len);
|
HMAC_Update(this->hmac, data.ptr, data.len);
|
||||||
if (out == NULL)
|
if (out == NULL)
|
||||||
{
|
{
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
HMAC_Final(&this->hmac, out, NULL);
|
HMAC_Final(this->hmac, out, NULL);
|
||||||
#endif
|
#endif
|
||||||
return set_key(this, chunk_empty);
|
return set_key(this, chunk_empty);
|
||||||
}
|
}
|
||||||
@@ -133,7 +140,11 @@ METHOD(mac_t, get_mac_size, size_t,
|
|||||||
METHOD(mac_t, destroy, void,
|
METHOD(mac_t, destroy, void,
|
||||||
private_mac_t *this)
|
private_mac_t *this)
|
||||||
{
|
{
|
||||||
HMAC_CTX_cleanup(&this->hmac);
|
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||||
|
HMAC_CTX_free(this->hmac);
|
||||||
|
#else
|
||||||
|
HMAC_CTX_cleanup(&this->hmac_ctx);
|
||||||
|
#endif
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,7 +178,12 @@ static mac_t *hmac_create(hash_algorithm_t algo)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
HMAC_CTX_init(&this->hmac);
|
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||||
|
this->hmac = HMAC_CTX_new();
|
||||||
|
#else
|
||||||
|
HMAC_CTX_init(&this->hmac_ctx);
|
||||||
|
this->hmac = &this->hmac_ctx;
|
||||||
|
#endif
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,10 @@
|
|||||||
#include <library.h>
|
#include <library.h>
|
||||||
#include <credentials/sets/mem_cred.h>
|
#include <credentials/sets/mem_cred.h>
|
||||||
|
|
||||||
|
#ifdef OPENSSL_IS_BORINGSSL
|
||||||
|
#define EVP_PKEY_base_id(p) EVP_PKEY_type(p->type)
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct private_pkcs12_t private_pkcs12_t;
|
typedef struct private_pkcs12_t private_pkcs12_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -110,7 +114,7 @@ static bool add_key(private_pkcs12_t *this, EVP_PKEY *private)
|
|||||||
{ /* no private key is ok */
|
{ /* no private key is ok */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
switch (EVP_PKEY_type(private->type))
|
switch (EVP_PKEY_base_id(private))
|
||||||
{
|
{
|
||||||
case EVP_PKEY_RSA:
|
case EVP_PKEY_RSA:
|
||||||
type = KEY_RSA;
|
type = KEY_RSA;
|
||||||
|
|||||||
@@ -29,6 +29,10 @@
|
|||||||
|
|
||||||
#include <openssl/cms.h>
|
#include <openssl/cms.h>
|
||||||
|
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
|
#define X509_ATTRIBUTE_get0_object(attr) ({ (attr)->object; })
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct private_openssl_pkcs7_t private_openssl_pkcs7_t;
|
typedef struct private_openssl_pkcs7_t private_openssl_pkcs7_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -432,11 +436,11 @@ METHOD(pkcs7_t, get_attribute, bool,
|
|||||||
for (i = 0; i < CMS_signed_get_attr_count(si); i++)
|
for (i = 0; i < CMS_signed_get_attr_count(si); i++)
|
||||||
{
|
{
|
||||||
attr = CMS_signed_get_attr(si, i);
|
attr = CMS_signed_get_attr(si, i);
|
||||||
if (!attr->single && sk_ASN1_TYPE_num(attr->value.set) == 1 &&
|
if (X509_ATTRIBUTE_count(attr) == 1 &&
|
||||||
openssl_asn1_known_oid(attr->object) == oid)
|
openssl_asn1_known_oid(X509_ATTRIBUTE_get0_object(attr)) == oid)
|
||||||
{
|
{
|
||||||
/* get first value in SET */
|
/* get first value in SET */
|
||||||
type = sk_ASN1_TYPE_value(attr->value.set, 0);
|
type = X509_ATTRIBUTE_get0_type(attr, 0);
|
||||||
chunk = wrapped = openssl_i2chunk(ASN1_TYPE, type);
|
chunk = wrapped = openssl_i2chunk(ASN1_TYPE, type);
|
||||||
if (asn1_unwrap(&chunk, &chunk) != 0x100 /* ASN1_INVALID */)
|
if (asn1_unwrap(&chunk, &chunk) != 0x100 /* ASN1_INVALID */)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -65,6 +65,11 @@ struct private_openssl_plugin_t {
|
|||||||
openssl_plugin_t public;
|
openssl_plugin_t public;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OpenSSL is thread-safe since 1.1.0
|
||||||
|
*/
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array of static mutexs, with CRYPTO_num_locks() mutex
|
* Array of static mutexs, with CRYPTO_num_locks() mutex
|
||||||
*/
|
*/
|
||||||
@@ -227,6 +232,14 @@ static void threading_cleanup()
|
|||||||
cleanup->destroy(cleanup);
|
cleanup->destroy(cleanup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else /* OPENSSL_VERSION_NUMBER */
|
||||||
|
|
||||||
|
#define threading_init()
|
||||||
|
|
||||||
|
#define threading_cleanup()
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Seed the OpenSSL RNG, if required
|
* Seed the OpenSSL RNG, if required
|
||||||
*/
|
*/
|
||||||
@@ -502,6 +515,10 @@ METHOD(plugin_t, get_features, int,
|
|||||||
METHOD(plugin_t, destroy, void,
|
METHOD(plugin_t, destroy, void,
|
||||||
private_openssl_plugin_t *this)
|
private_openssl_plugin_t *this)
|
||||||
{
|
{
|
||||||
|
/* OpenSSL 1.1.0 cleans up itself at exit and while OPENSSL_cleanup() exists we
|
||||||
|
* can't call it as we couldn't re-initialize the library (as required by the
|
||||||
|
* unit tests and the Android app) */
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
#ifndef OPENSSL_IS_BORINGSSL
|
#ifndef OPENSSL_IS_BORINGSSL
|
||||||
CONF_modules_free();
|
CONF_modules_free();
|
||||||
OBJ_cleanup();
|
OBJ_cleanup();
|
||||||
@@ -513,6 +530,7 @@ METHOD(plugin_t, destroy, void,
|
|||||||
CRYPTO_cleanup_all_ex_data();
|
CRYPTO_cleanup_all_ex_data();
|
||||||
threading_cleanup();
|
threading_cleanup();
|
||||||
ERR_free_strings();
|
ERR_free_strings();
|
||||||
|
#endif /* OPENSSL_VERSION_NUMBER */
|
||||||
|
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
@@ -555,12 +573,23 @@ plugin_t *openssl_plugin_create()
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||||
|
/* note that we can't call OPENSSL_cleanup() when the plugin is destroyed
|
||||||
|
* as we couldn't initialize the library again afterwards */
|
||||||
|
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG |
|
||||||
|
OPENSSL_INIT_ENGINE_ALL_BUILTIN, NULL);
|
||||||
|
#else /* OPENSSL_VERSION_NUMBER */
|
||||||
threading_init();
|
threading_init();
|
||||||
|
|
||||||
#ifndef OPENSSL_IS_BORINGSSL
|
#ifndef OPENSSL_IS_BORINGSSL
|
||||||
OPENSSL_config(NULL);
|
OPENSSL_config(NULL);
|
||||||
#endif
|
#endif
|
||||||
OpenSSL_add_all_algorithms();
|
OpenSSL_add_all_algorithms();
|
||||||
|
#ifndef OPENSSL_NO_ENGINE
|
||||||
|
/* activate support for hardware accelerators */
|
||||||
|
ENGINE_load_builtin_engines();
|
||||||
|
ENGINE_register_all_complete();
|
||||||
|
#endif /* OPENSSL_NO_ENGINE */
|
||||||
|
#endif /* OPENSSL_VERSION_NUMBER */
|
||||||
|
|
||||||
#ifdef OPENSSL_FIPS
|
#ifdef OPENSSL_FIPS
|
||||||
/* we do this here as it may have been enabled via openssl.conf */
|
/* we do this here as it may have been enabled via openssl.conf */
|
||||||
@@ -569,12 +598,6 @@ plugin_t *openssl_plugin_create()
|
|||||||
"openssl FIPS mode(%d) - %sabled ", fips_mode, fips_mode ? "en" : "dis");
|
"openssl FIPS mode(%d) - %sabled ", fips_mode, fips_mode ? "en" : "dis");
|
||||||
#endif /* OPENSSL_FIPS */
|
#endif /* OPENSSL_FIPS */
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_ENGINE
|
|
||||||
/* activate support for hardware accelerators */
|
|
||||||
ENGINE_load_builtin_engines();
|
|
||||||
ENGINE_register_all_complete();
|
|
||||||
#endif /* OPENSSL_NO_ENGINE */
|
|
||||||
|
|
||||||
if (!seed_rng())
|
if (!seed_rng())
|
||||||
{
|
{
|
||||||
DBG1(DBG_CFG, "no RNG found to seed OpenSSL");
|
DBG1(DBG_CFG, "no RNG found to seed OpenSSL");
|
||||||
|
|||||||
@@ -49,13 +49,6 @@ struct private_openssl_rng_t {
|
|||||||
METHOD(rng_t, get_bytes, bool,
|
METHOD(rng_t, get_bytes, bool,
|
||||||
private_openssl_rng_t *this, size_t bytes, uint8_t *buffer)
|
private_openssl_rng_t *this, size_t bytes, uint8_t *buffer)
|
||||||
{
|
{
|
||||||
if (this->quality == RNG_WEAK)
|
|
||||||
{
|
|
||||||
/* RAND_pseudo_bytes() returns 1 if returned bytes are strong,
|
|
||||||
* 0 if of not. Both is acceptable for RNG_WEAK. */
|
|
||||||
return RAND_pseudo_bytes((char*)buffer, bytes) != -1;
|
|
||||||
}
|
|
||||||
/* A 0 return value is a failure for RAND_bytes() */
|
|
||||||
return RAND_bytes((char*)buffer, bytes) == 1;
|
return RAND_bytes((char*)buffer, bytes) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "openssl_rsa_private_key.h"
|
#include "openssl_rsa_private_key.h"
|
||||||
#include "openssl_rsa_public_key.h"
|
#include "openssl_rsa_public_key.h"
|
||||||
|
#include "openssl_util.h"
|
||||||
|
|
||||||
#include <utils/debug.h>
|
#include <utils/debug.h>
|
||||||
|
|
||||||
@@ -35,6 +36,12 @@
|
|||||||
*/
|
*/
|
||||||
#define PUBLIC_EXPONENT 0x10001
|
#define PUBLIC_EXPONENT 0x10001
|
||||||
|
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
|
OPENSSL_KEY_FALLBACK(RSA, key, n, e, d)
|
||||||
|
OPENSSL_KEY_FALLBACK(RSA, factors, p, q)
|
||||||
|
OPENSSL_KEY_FALLBACK(RSA, crt_params, dmp1, dmq1, iqmp)
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct private_openssl_rsa_private_key_t private_openssl_rsa_private_key_t;
|
typedef struct private_openssl_rsa_private_key_t private_openssl_rsa_private_key_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -436,22 +443,38 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_load(key_type_t type,
|
|||||||
}
|
}
|
||||||
else if (n.ptr && e.ptr && d.ptr && p.ptr && q.ptr && coeff.ptr)
|
else if (n.ptr && e.ptr && d.ptr && p.ptr && q.ptr && coeff.ptr)
|
||||||
{
|
{
|
||||||
|
BIGNUM *bn_n, *bn_e, *bn_d, *bn_p, *bn_q;
|
||||||
|
BIGNUM *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL;
|
||||||
|
|
||||||
this->rsa = RSA_new();
|
this->rsa = RSA_new();
|
||||||
this->rsa->n = BN_bin2bn((const u_char*)n.ptr, n.len, NULL);
|
|
||||||
this->rsa->e = BN_bin2bn((const u_char*)e.ptr, e.len, NULL);
|
bn_n = BN_bin2bn((const u_char*)n.ptr, n.len, NULL);
|
||||||
this->rsa->d = BN_bin2bn((const u_char*)d.ptr, d.len, NULL);
|
bn_e = BN_bin2bn((const u_char*)e.ptr, e.len, NULL);
|
||||||
this->rsa->p = BN_bin2bn((const u_char*)p.ptr, p.len, NULL);
|
bn_d = BN_bin2bn((const u_char*)d.ptr, d.len, NULL);
|
||||||
this->rsa->q = BN_bin2bn((const u_char*)q.ptr, q.len, NULL);
|
if (!RSA_set0_key(this->rsa, bn_n, bn_e, bn_d))
|
||||||
|
{
|
||||||
|
destroy(this);
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
bn_p = BN_bin2bn((const u_char*)p.ptr, p.len, NULL);
|
||||||
|
bn_q = BN_bin2bn((const u_char*)q.ptr, q.len, NULL);
|
||||||
|
if (!RSA_set0_factors(this->rsa, bn_p, bn_q))
|
||||||
|
{
|
||||||
|
destroy(this);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
if (exp1.ptr)
|
if (exp1.ptr)
|
||||||
{
|
{
|
||||||
this->rsa->dmp1 = BN_bin2bn((const u_char*)exp1.ptr, exp1.len, NULL);
|
dmp1 = BN_bin2bn((const u_char*)exp1.ptr, exp1.len, NULL);
|
||||||
}
|
}
|
||||||
if (exp2.ptr)
|
if (exp2.ptr)
|
||||||
{
|
{
|
||||||
this->rsa->dmq1 = BN_bin2bn((const u_char*)exp2.ptr, exp2.len, NULL);
|
dmq1 = BN_bin2bn((const u_char*)exp2.ptr, exp2.len, NULL);
|
||||||
}
|
}
|
||||||
this->rsa->iqmp = BN_bin2bn((const u_char*)coeff.ptr, coeff.len, NULL);
|
iqmp = BN_bin2bn((const u_char*)coeff.ptr, coeff.len, NULL);
|
||||||
if (RSA_check_key(this->rsa) == 1)
|
if (RSA_set0_crt_params(this->rsa, dmp1, dmq1, iqmp) &&
|
||||||
|
RSA_check_key(this->rsa) == 1)
|
||||||
{
|
{
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,10 @@
|
|||||||
#include <openssl/rsa.h>
|
#include <openssl/rsa.h>
|
||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
|
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
|
OPENSSL_KEY_FALLBACK(RSA, key, n, e, d)
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct private_openssl_rsa_public_key_t private_openssl_rsa_public_key_t;
|
typedef struct private_openssl_rsa_public_key_t private_openssl_rsa_public_key_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -224,11 +228,13 @@ bool openssl_rsa_fingerprint(RSA *rsa, cred_encoding_type_t type, chunk_t *fp)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
const BIGNUM *bn_n, *bn_e;
|
||||||
chunk_t n = chunk_empty, e = chunk_empty;
|
chunk_t n = chunk_empty, e = chunk_empty;
|
||||||
bool success = FALSE;
|
bool success = FALSE;
|
||||||
|
|
||||||
if (openssl_bn2chunk(rsa->n, &n) &&
|
RSA_get0_key(rsa, &bn_n, &bn_e, NULL);
|
||||||
openssl_bn2chunk(rsa->e, &e))
|
if (openssl_bn2chunk(bn_n, &n) &&
|
||||||
|
openssl_bn2chunk(bn_e, &e))
|
||||||
{
|
{
|
||||||
success = lib->encoding->encode(lib->encoding, type, rsa, fp,
|
success = lib->encoding->encode(lib->encoding, type, rsa, fp,
|
||||||
CRED_PART_RSA_MODULUS, n,
|
CRED_PART_RSA_MODULUS, n,
|
||||||
@@ -297,10 +303,12 @@ METHOD(public_key_t, get_encoding, bool,
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
const BIGNUM *bn_n, *bn_e;
|
||||||
chunk_t n = chunk_empty, e = chunk_empty;
|
chunk_t n = chunk_empty, e = chunk_empty;
|
||||||
|
|
||||||
if (openssl_bn2chunk(this->rsa->n, &n) &&
|
RSA_get0_key(this->rsa, &bn_n, &bn_e, NULL);
|
||||||
openssl_bn2chunk(this->rsa->e, &e))
|
if (openssl_bn2chunk(bn_n, &n) &&
|
||||||
|
openssl_bn2chunk(bn_e, &e))
|
||||||
{
|
{
|
||||||
success = lib->encoding->encode(lib->encoding, type, NULL,
|
success = lib->encoding->encode(lib->encoding, type, NULL,
|
||||||
encoding, CRED_PART_RSA_MODULUS, n,
|
encoding, CRED_PART_RSA_MODULUS, n,
|
||||||
@@ -416,11 +424,16 @@ openssl_rsa_public_key_t *openssl_rsa_public_key_load(key_type_t type,
|
|||||||
}
|
}
|
||||||
else if (n.ptr && e.ptr && type == KEY_RSA)
|
else if (n.ptr && e.ptr && type == KEY_RSA)
|
||||||
{
|
{
|
||||||
|
BIGNUM *bn_n, *bn_e;
|
||||||
|
|
||||||
this->rsa = RSA_new();
|
this->rsa = RSA_new();
|
||||||
this->rsa->n = BN_bin2bn((const u_char*)n.ptr, n.len, NULL);
|
bn_n = BN_bin2bn((const u_char*)n.ptr, n.len, NULL);
|
||||||
this->rsa->e = BN_bin2bn((const u_char*)e.ptr, e.len, NULL);
|
bn_e = BN_bin2bn((const u_char*)e.ptr, e.len, NULL);
|
||||||
|
if (RSA_set0_key(this->rsa, bn_n, bn_e, NULL))
|
||||||
|
{
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
destroy(this);
|
destroy(this);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,12 @@
|
|||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
|
|
||||||
|
/* these were added with 1.1.0 when ASN1_OBJECT was made opaque */
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
|
#define OBJ_get0_data(o) ((o)->data)
|
||||||
|
#define OBJ_length(o) ((o)->length)
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Described in header.
|
* Described in header.
|
||||||
*/
|
*/
|
||||||
@@ -70,7 +76,8 @@ error:
|
|||||||
/**
|
/**
|
||||||
* Described in header.
|
* Described in header.
|
||||||
*/
|
*/
|
||||||
bool openssl_bn_cat(int len, BIGNUM *a, BIGNUM *b, chunk_t *chunk)
|
bool openssl_bn_cat(const int len, const BIGNUM *a, const BIGNUM *b,
|
||||||
|
chunk_t *chunk)
|
||||||
{
|
{
|
||||||
int offset;
|
int offset;
|
||||||
|
|
||||||
@@ -127,7 +134,7 @@ bool openssl_bn_split(chunk_t chunk, BIGNUM *a, BIGNUM *b)
|
|||||||
/**
|
/**
|
||||||
* Described in header.
|
* Described in header.
|
||||||
*/
|
*/
|
||||||
bool openssl_bn2chunk(BIGNUM *bn, chunk_t *chunk)
|
bool openssl_bn2chunk(const BIGNUM *bn, chunk_t *chunk)
|
||||||
{
|
{
|
||||||
*chunk = chunk_alloc(BN_num_bytes(bn));
|
*chunk = chunk_alloc(BN_num_bytes(bn));
|
||||||
if (BN_bn2bin(bn, chunk->ptr) == chunk->len)
|
if (BN_bn2bin(bn, chunk->ptr) == chunk->len)
|
||||||
@@ -149,7 +156,7 @@ chunk_t openssl_asn1_obj2chunk(ASN1_OBJECT *asn1)
|
|||||||
{
|
{
|
||||||
if (asn1)
|
if (asn1)
|
||||||
{
|
{
|
||||||
return chunk_create((u_char*)asn1->data, asn1->length);
|
return chunk_create((u_char*)OBJ_get0_data(asn1), OBJ_length(asn1));
|
||||||
}
|
}
|
||||||
return chunk_empty;
|
return chunk_empty;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,8 @@ bool openssl_hash_chunk(int hash_type, chunk_t data, chunk_t *hash);
|
|||||||
* @param chunk resulting chunk
|
* @param chunk resulting chunk
|
||||||
* @return TRUE on success, FALSE otherwise
|
* @return TRUE on success, FALSE otherwise
|
||||||
*/
|
*/
|
||||||
bool openssl_bn_cat(int len, BIGNUM *a, BIGNUM *b, chunk_t *chunk);
|
bool openssl_bn_cat(const int len, const BIGNUM *a, const BIGNUM *b,
|
||||||
|
chunk_t *chunk);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Splits a chunk into two bignums of equal binary length.
|
* Splits a chunk into two bignums of equal binary length.
|
||||||
@@ -80,7 +81,7 @@ bool openssl_bn_split(chunk_t chunk, BIGNUM *a, BIGNUM *b);
|
|||||||
* @param chunk the chunk (data gets allocated)
|
* @param chunk the chunk (data gets allocated)
|
||||||
* @return TRUE on success, FALSE otherwise
|
* @return TRUE on success, FALSE otherwise
|
||||||
*/
|
*/
|
||||||
bool openssl_bn2chunk(BIGNUM *bn, chunk_t *chunk);
|
bool openssl_bn2chunk(const BIGNUM *bn, chunk_t *chunk);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate a chunk using the i2d function of a given object
|
* Allocate a chunk using the i2d function of a given object
|
||||||
@@ -134,4 +135,42 @@ int openssl_asn1_known_oid(ASN1_OBJECT *obj);
|
|||||||
*/
|
*/
|
||||||
time_t openssl_asn1_to_time(ASN1_TIME *time);
|
time_t openssl_asn1_to_time(ASN1_TIME *time);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Macros to define fallback getters/setters to access keys (BIGNUM*) for types
|
||||||
|
* that were made opaque with OpenSSL 1.1.0.
|
||||||
|
*/
|
||||||
|
#define OPENSSL_KEY_FALLBACK(...) VA_ARGS_DISPATCH(OPENSSL_KEY_FALLBACK, __VA_ARGS__)(__VA_ARGS__)
|
||||||
|
#define OPENSSL_KEY_FALLBACK3(type, k1, k2) \
|
||||||
|
__attribute__((unused)) \
|
||||||
|
static inline void type##_get0(const type *o, const BIGNUM **k1, const BIGNUM **k2) { \
|
||||||
|
if (k1) *k1 = o->k1; \
|
||||||
|
if (k2) *k2 = o->k2; } \
|
||||||
|
__attribute__((unused)) \
|
||||||
|
static inline int type##_set0(type *o, BIGNUM *k1, BIGNUM *k2) { \
|
||||||
|
if (k1) { BN_clear_free(o->k1); o->k1 = k1; } \
|
||||||
|
if (k2) { BN_clear_free(o->k2); o->k2 = k2; } \
|
||||||
|
return 1; }
|
||||||
|
#define OPENSSL_KEY_FALLBACK4(type, name, k1, k2) \
|
||||||
|
__attribute__((unused)) \
|
||||||
|
static inline void type##_get0_##name(const type *o, const BIGNUM **k1, const BIGNUM **k2) { \
|
||||||
|
if (k1) *k1 = o->k1; \
|
||||||
|
if (k2) *k2 = o->k2; } \
|
||||||
|
__attribute__((unused)) \
|
||||||
|
static inline int type##_set0_##name(type *o, BIGNUM *k1, BIGNUM *k2) { \
|
||||||
|
if (k1) { BN_clear_free(o->k1); o->k1 = k1; } \
|
||||||
|
if (k2) { BN_clear_free(o->k2); o->k2 = k2; } \
|
||||||
|
return 1; }
|
||||||
|
#define OPENSSL_KEY_FALLBACK5(type, name, k1, k2, k3) \
|
||||||
|
__attribute__((unused)) \
|
||||||
|
static inline void type##_get0_##name(const type *o, const BIGNUM **k1, const BIGNUM **k2, const BIGNUM **k3) { \
|
||||||
|
if (k1) *k1 = o->k1; \
|
||||||
|
if (k2) *k2 = o->k2; \
|
||||||
|
if (k3) *k3 = o->k3; } \
|
||||||
|
__attribute__((unused)) \
|
||||||
|
static inline int type##_set0_##name(type *o, BIGNUM *k1, BIGNUM *k2, BIGNUM *k3) { \
|
||||||
|
if (k1) { BN_clear_free(o->k1); o->k1 = k1; } \
|
||||||
|
if (k2) { BN_clear_free(o->k2); o->k2 = k2; } \
|
||||||
|
if (k3) { BN_clear_free(o->k3); o->k3 = k3; } \
|
||||||
|
return 1; }
|
||||||
|
|
||||||
#endif /** OPENSSL_UTIL_H_ @}*/
|
#endif /** OPENSSL_UTIL_H_ @}*/
|
||||||
|
|||||||
@@ -60,6 +60,25 @@
|
|||||||
#define OPENSSL_NO_RFC3779
|
#define OPENSSL_NO_RFC3779
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* added with 1.0.2 */
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x10002000L
|
||||||
|
static inline void X509_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg, const X509 *x) {
|
||||||
|
if (psig) { *psig = x->signature; }
|
||||||
|
if (palg) { *palg = x->sig_alg; }
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* added with 1.1.0 when X509 etc. was made opaque */
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
|
#define X509_get0_extensions(x509) ({ (x509)->cert_info->extensions; })
|
||||||
|
#define X509_get0_tbs_sigalg(x509) ({ (x509)->cert_info->signature; })
|
||||||
|
#define X509_ALGOR_get0(oid, ppt, ppv, alg) ({ *(oid) = (alg)->algorithm; })
|
||||||
|
#define X509_PUBKEY_get0_param(oid, pk, len, pa, pub) X509_ALGOR_get0(oid, NULL, NULL, (pub)->algor)
|
||||||
|
#define X509v3_addr_get_afi v3_addr_get_afi
|
||||||
|
#define X509v3_addr_get_range v3_addr_get_range
|
||||||
|
#define X509v3_addr_is_canonical v3_addr_is_canonical
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct private_openssl_x509_t private_openssl_x509_t;
|
typedef struct private_openssl_x509_t private_openssl_x509_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -380,6 +399,7 @@ METHOD(certificate_t, issued_by, bool,
|
|||||||
public_key_t *key;
|
public_key_t *key;
|
||||||
bool valid;
|
bool valid;
|
||||||
x509_t *x509 = (x509_t*)issuer;
|
x509_t *x509 = (x509_t*)issuer;
|
||||||
|
ASN1_BIT_STRING *sig;
|
||||||
chunk_t tbs;
|
chunk_t tbs;
|
||||||
|
|
||||||
if (&this->public.x509.interface == issuer)
|
if (&this->public.x509.interface == issuer)
|
||||||
@@ -413,9 +433,14 @@ METHOD(certificate_t, issued_by, bool,
|
|||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
/* i2d_re_X509_tbs() was added with 1.1.0 when X509 was made opaque */
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||||
|
tbs = openssl_i2chunk(re_X509_tbs, this->x509);
|
||||||
|
#else
|
||||||
tbs = openssl_i2chunk(X509_CINF, this->x509->cert_info);
|
tbs = openssl_i2chunk(X509_CINF, this->x509->cert_info);
|
||||||
valid = key->verify(key, this->scheme, tbs,
|
#endif
|
||||||
openssl_asn1_str2chunk(this->x509->signature));
|
X509_get0_signature(&sig, NULL, this->x509);
|
||||||
|
valid = key->verify(key, this->scheme, tbs, openssl_asn1_str2chunk(sig));
|
||||||
free(tbs.ptr);
|
free(tbs.ptr);
|
||||||
key->destroy(key);
|
key->destroy(key);
|
||||||
if (valid && scheme)
|
if (valid && scheme)
|
||||||
@@ -850,7 +875,7 @@ static void parse_ipAddrBlock_ext_fam(private_openssl_x509_t *this,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
afi = v3_addr_get_afi(fam);
|
afi = X509v3_addr_get_afi(fam);
|
||||||
switch (afi)
|
switch (afi)
|
||||||
{
|
{
|
||||||
case IANA_AFI_IPV4:
|
case IANA_AFI_IPV4:
|
||||||
@@ -871,7 +896,7 @@ static void parse_ipAddrBlock_ext_fam(private_openssl_x509_t *this,
|
|||||||
for (i = 0; i < sk_IPAddressOrRange_num(list); i++)
|
for (i = 0; i < sk_IPAddressOrRange_num(list); i++)
|
||||||
{
|
{
|
||||||
aor = sk_IPAddressOrRange_value(list, i);
|
aor = sk_IPAddressOrRange_value(list, i);
|
||||||
if (v3_addr_get_range(aor, afi, from.ptr, to.ptr, from.len) > 0)
|
if (X509v3_addr_get_range(aor, afi, from.ptr, to.ptr, from.len) > 0)
|
||||||
{
|
{
|
||||||
ts = traffic_selector_create_from_bytes(0, type, from, 0, to, 65535);
|
ts = traffic_selector_create_from_bytes(0, type, from, 0, to, 65535);
|
||||||
if (ts)
|
if (ts)
|
||||||
@@ -897,7 +922,7 @@ static bool parse_ipAddrBlock_ext(private_openssl_x509_t *this,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!v3_addr_is_canonical(blocks))
|
if (!X509v3_addr_is_canonical(blocks))
|
||||||
{
|
{
|
||||||
sk_IPAddressFamily_free(blocks);
|
sk_IPAddressFamily_free(blocks);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@@ -964,7 +989,7 @@ static bool parse_extensions(private_openssl_x509_t *this)
|
|||||||
STACK_OF(X509_EXTENSION) *extensions;
|
STACK_OF(X509_EXTENSION) *extensions;
|
||||||
int i, num;
|
int i, num;
|
||||||
|
|
||||||
extensions = this->x509->cert_info->extensions;
|
extensions = X509_get0_extensions(this->x509);
|
||||||
if (extensions)
|
if (extensions)
|
||||||
{
|
{
|
||||||
num = sk_X509_EXTENSION_num(extensions);
|
num = sk_X509_EXTENSION_num(extensions);
|
||||||
@@ -1041,6 +1066,8 @@ static bool parse_certificate(private_openssl_x509_t *this)
|
|||||||
const unsigned char *ptr = this->encoding.ptr;
|
const unsigned char *ptr = this->encoding.ptr;
|
||||||
hasher_t *hasher;
|
hasher_t *hasher;
|
||||||
chunk_t chunk;
|
chunk_t chunk;
|
||||||
|
ASN1_OBJECT *oid, *oid_tbs;
|
||||||
|
X509_ALGOR *alg;
|
||||||
|
|
||||||
this->x509 = d2i_X509(NULL, &ptr, this->encoding.len);
|
this->x509 = d2i_X509(NULL, &ptr, this->encoding.len);
|
||||||
if (!this->x509)
|
if (!this->x509)
|
||||||
@@ -1057,7 +1084,12 @@ static bool parse_certificate(private_openssl_x509_t *this)
|
|||||||
this->subject = openssl_x509_name2id(X509_get_subject_name(this->x509));
|
this->subject = openssl_x509_name2id(X509_get_subject_name(this->x509));
|
||||||
this->issuer = openssl_x509_name2id(X509_get_issuer_name(this->x509));
|
this->issuer = openssl_x509_name2id(X509_get_issuer_name(this->x509));
|
||||||
|
|
||||||
switch (openssl_asn1_known_oid(this->x509->cert_info->key->algor->algorithm))
|
if (!X509_PUBKEY_get0_param(&oid, NULL, NULL, NULL,
|
||||||
|
X509_get_X509_PUBKEY(this->x509)))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
switch (openssl_asn1_known_oid(oid))
|
||||||
{
|
{
|
||||||
case OID_RSA_ENCRYPTION:
|
case OID_RSA_ENCRYPTION:
|
||||||
this->pubkey = lib->creds->create(lib->creds,
|
this->pubkey = lib->creds->create(lib->creds,
|
||||||
@@ -1086,14 +1118,18 @@ static bool parse_certificate(private_openssl_x509_t *this)
|
|||||||
this->notBefore = openssl_asn1_to_time(X509_get_notBefore(this->x509));
|
this->notBefore = openssl_asn1_to_time(X509_get_notBefore(this->x509));
|
||||||
this->notAfter = openssl_asn1_to_time(X509_get_notAfter(this->x509));
|
this->notAfter = openssl_asn1_to_time(X509_get_notAfter(this->x509));
|
||||||
|
|
||||||
if (!chunk_equals(
|
/* while X509_ALGOR_cmp() is declared in the headers of older OpenSSL
|
||||||
openssl_asn1_obj2chunk(this->x509->cert_info->signature->algorithm),
|
* versions, at least on Ubuntu 14.04 it is not actually defined */
|
||||||
openssl_asn1_obj2chunk(this->x509->sig_alg->algorithm)))
|
X509_get0_signature(NULL, &alg, this->x509);
|
||||||
|
X509_ALGOR_get0(&oid, NULL, NULL, alg);
|
||||||
|
alg = X509_get0_tbs_sigalg(this->x509);
|
||||||
|
X509_ALGOR_get0(&oid_tbs, NULL, NULL, alg);
|
||||||
|
if (!chunk_equals(openssl_asn1_obj2chunk(oid),
|
||||||
|
openssl_asn1_obj2chunk(oid_tbs)))
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
this->scheme = signature_scheme_from_oid(openssl_asn1_known_oid(
|
this->scheme = signature_scheme_from_oid(openssl_asn1_known_oid(oid));
|
||||||
this->x509->sig_alg->algorithm));
|
|
||||||
|
|
||||||
if (!parse_extensions(this))
|
if (!parse_extensions(this))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -564,6 +564,10 @@ char *whitelist[] = {
|
|||||||
"ECDSA_do_sign_ex",
|
"ECDSA_do_sign_ex",
|
||||||
"ECDSA_verify",
|
"ECDSA_verify",
|
||||||
"RSA_new_method",
|
"RSA_new_method",
|
||||||
|
/* OpenSSL 1.1.0 does not cleanup anymore until the library is unloaded */
|
||||||
|
"OPENSSL_init_crypto",
|
||||||
|
"CRYPTO_THREAD_lock_new",
|
||||||
|
"ERR_add_error_data",
|
||||||
/* OpenSSL libssl */
|
/* OpenSSL libssl */
|
||||||
"SSL_COMP_get_compression_methods",
|
"SSL_COMP_get_compression_methods",
|
||||||
/* NSPR */
|
/* NSPR */
|
||||||
@@ -840,6 +844,18 @@ HOOK(void, free, void *ptr)
|
|||||||
|
|
||||||
if (!enabled || thread_disabled->get(thread_disabled))
|
if (!enabled || thread_disabled->get(thread_disabled))
|
||||||
{
|
{
|
||||||
|
/* after deinitialization we might have to free stuff we allocated
|
||||||
|
* while we were enabled */
|
||||||
|
if (!first_header.magic && ptr)
|
||||||
|
{
|
||||||
|
hdr = ptr - sizeof(memory_header_t);
|
||||||
|
tail = ptr + hdr->bytes;
|
||||||
|
if (hdr->magic == MEMORY_HEADER_MAGIC &&
|
||||||
|
tail->magic == MEMORY_TAIL_MAGIC)
|
||||||
|
{
|
||||||
|
ptr = hdr;
|
||||||
|
}
|
||||||
|
}
|
||||||
real_free(ptr);
|
real_free(ptr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -956,6 +972,7 @@ METHOD(leak_detective_t, destroy, void,
|
|||||||
lock->destroy(lock);
|
lock->destroy(lock);
|
||||||
thread_disabled->destroy(thread_disabled);
|
thread_disabled->destroy(thread_disabled);
|
||||||
free(this);
|
free(this);
|
||||||
|
first_header.magic = 0;
|
||||||
first_header.next = NULL;
|
first_header.next = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user