};
struct dcrypt_public_key {
- void *ctx;
+ EVP_PKEY *key;
+ unsigned int ref;
};
struct dcrypt_private_key {
- void *ctx;
+ EVP_PKEY *key;
+ unsigned int ref;
};
static
static
void dcrypt_openssl_private_to_public_key(struct dcrypt_private_key *priv_key, struct dcrypt_public_key **pub_key_r);
static
-void dcrypt_openssl_free_private_key(struct dcrypt_private_key **key);
+void dcrypt_openssl_unref_private_key(struct dcrypt_private_key **key);
static
-void dcrypt_openssl_free_public_key(struct dcrypt_public_key **key);
+void dcrypt_openssl_unref_public_key(struct dcrypt_public_key **key);
static
bool dcrypt_openssl_rsa_decrypt(struct dcrypt_private_key *key, const unsigned char *data, size_t data_len, buffer_t *result, const char **error_r);
bool dcrypt_openssl_ecdh_derive_secret_local(struct dcrypt_private_key *local_key, buffer_t *R, buffer_t *S, const char **error_r)
{
i_assert(local_key != NULL);
- EVP_PKEY *local = (EVP_PKEY*)local_key;
+ EVP_PKEY *local = local_key->key;
BN_CTX *bn_ctx = BN_CTX_new();
if (bn_ctx == NULL)
return dcrypt_openssl_error(error_r);
{
/* ensure peer_key is EC key */
EVP_PKEY *local = NULL;
- EVP_PKEY *peer = (EVP_PKEY*)peer_key;
+ EVP_PKEY *peer = peer_key->key;
if (EVP_PKEY_base_id(peer) != EVP_PKEY_EC) {
if (error_r != NULL)
*error_r = "Only ECC key can be used";
EVP_PKEY *pkey = NULL;
if (kind == DCRYPT_KEY_RSA) {
if (dcrypt_openssl_generate_rsa_key(bits, &pkey, error_r)) {
- pair_r->priv = (struct dcrypt_private_key*)pkey;
+ pair_r->priv = i_new(struct dcrypt_private_key, 1);
+ pair_r->priv->key = pkey;
+ pair_r->priv->ref++;
+ pair_r->pub = NULL;
dcrypt_openssl_private_to_public_key(pair_r->priv, &(pair_r->pub));
return TRUE;
} else return dcrypt_openssl_error(error_r);
return FALSE;
}
if (dcrypt_openssl_generate_ec_key(nid, &pkey, error_r)) {
- pair_r->priv = (struct dcrypt_private_key*)pkey;
+ pair_r->priv = i_new(struct dcrypt_private_key, 1);
+ pair_r->priv->key = pkey;
+ pair_r->priv->ref++;
+ pair_r->pub = NULL;
dcrypt_openssl_private_to_public_key(pair_r->priv, &(pair_r->pub));
return TRUE;
} else return dcrypt_openssl_error(error_r);
}
EVP_PKEY_set1_EC_KEY(key, eckey);
EC_KEY_free(eckey);
- *key_r = (struct dcrypt_private_key *)key;
+ *key_r = i_new(struct dcrypt_private_key, 1);
+ (*key_r)->key = key;
+ (*key_r)->ref++;
return TRUE;
}
/* check that we have correct decryption key */
dcrypt_openssl_private_to_public_key(dec_key, &pubkey);
if (!dcrypt_openssl_public_key_id(pubkey, "sha256", data, error_r)) {
- if (pubkey != NULL) dcrypt_openssl_free_public_key(&pubkey);
+ if (pubkey != NULL) dcrypt_openssl_unref_public_key(&pubkey);
return FALSE;
}
- dcrypt_openssl_free_public_key(&pubkey);
+ dcrypt_openssl_unref_public_key(&pubkey);
if (strcmp(binary_to_hex(data->data, data->used), input[9]) != 0) {
- dcrypt_openssl_free_public_key(&pubkey);
+ dcrypt_openssl_unref_public_key(&pubkey);
if (error_r != NULL)
*error_r = "No private key available";
return FALSE;
}
EVP_PKEY_set1_RSA(pkey, rsa);
RSA_free(rsa);
- *key_r = (struct dcrypt_private_key *)pkey;
+ *key_r = i_new(struct dcrypt_private_key, 1);
+ (*key_r)->key = pkey;
+ (*key_r)->ref++;
} else {
int ec;
BIGNUM *point = BN_new();
if (ec == 1 && key != NULL && EC_KEY_check_key(eckey) == 1) {
EVP_PKEY_set1_EC_KEY(key, eckey);
EC_KEY_free(eckey);
- *key_r = (struct dcrypt_private_key *)key;
+ *key_r = i_new(struct dcrypt_private_key, 1);
+ (*key_r)->key = key;
+ (*key_r)->ref++;
} else {
EVP_PKEY_free(key);
EC_KEY_free(eckey);
dcrypt_openssl_private_key_id(*key_r, "sha256", key_data, NULL);
if (strcmp(binary_to_hex(key_data->data, key_data->used), input[len-1]) != 0) {
- dcrypt_openssl_free_private_key(key_r);
+ dcrypt_openssl_unref_private_key(key_r);
if (error_r != NULL)
*error_r = "Key id mismatch after load";
return FALSE;
EC_KEY_free(eckey);
/* make sure digest matches */
buffer_t *dgst = buffer_create_dynamic(pool_datastack_create(), 32);
- dcrypt_openssl_public_key_id_old((struct dcrypt_public_key *)key, dgst, NULL);
+ struct dcrypt_public_key tmp = { key, 0 };
+ dcrypt_openssl_public_key_id_old(&tmp, dgst, NULL);
if (strcmp(binary_to_hex(dgst->data, dgst->used), input[len-1]) != 0) {
if (error_r != NULL)
*error_r = "Key id mismatch after load";
EVP_PKEY_free(key);
return -1;
}
- *key_r = (struct dcrypt_public_key *)key;
+ *key_r = i_new(struct dcrypt_public_key, 1);
+ (*key_r)->key = key;
+ (*key_r)->ref++;
return 0;
}
/* make sure digest matches */
buffer_t *dgst = buffer_create_dynamic(pool_datastack_create(), 32);
- dcrypt_openssl_public_key_id((struct dcrypt_public_key *)pkey, "sha256", dgst, NULL);
+ struct dcrypt_public_key tmpkey = {pkey, 0};
+ dcrypt_openssl_public_key_id(&tmpkey, "sha256", dgst, NULL);
if (strcmp(binary_to_hex(dgst->data, dgst->used), input[len-1]) != 0) {
if (error_r != NULL)
*error_r = "Key id mismatch after load";
return -1;
}
- *key_r = (struct dcrypt_public_key *)pkey;
+ *key_r = i_new(struct dcrypt_public_key, 1);
+ (*key_r)->key = pkey;
+ (*key_r)->ref++;
return 0;
}
DCRYPT_DOVECOT_KEY_ENCRYPT_ROUNDS));
if (enctype == DCRYPT_DOVECOT_KEY_ENCRYPT_PK) {
- if (EVP_PKEY_base_id((EVP_PKEY*)enc_key) == EVP_PKEY_RSA) {
+ if (EVP_PKEY_base_id(enc_key->key) == EVP_PKEY_RSA) {
size_t used = buffer_get_used_size(secret);
/* peer key, in this case, is encrypted secret, which is 16 bytes of data */
ptr = buffer_append_space_unsafe(secret, 16);
if (!dcrypt_rsa_encrypt(enc_key, secret->data, secret->used, peer_key, error_r)) {
return FALSE;
}
- } else if (EVP_PKEY_base_id((EVP_PKEY*)enc_key) == EVP_PKEY_EC) {
+ } else if (EVP_PKEY_base_id(enc_key->key) == EVP_PKEY_EC) {
/* generate secret by ECDHE */
if (!dcrypt_openssl_ecdh_derive_secret_peer(enc_key, peer_key, secret, error_r)) {
return FALSE;
{
size_t dest_used = buffer_get_used_size(destination);
const char *cipher2 = NULL;
- EVP_PKEY *pkey = (EVP_PKEY*)key;
+ EVP_PKEY *pkey = key->key;
char objtxt[80]; /* openssl manual says this is OK */
ASN1_OBJECT *obj;
if (EVP_PKEY_base_id(pkey) == EVP_PKEY_EC) {
static
bool dcrypt_openssl_store_public_key_dovecot(struct dcrypt_public_key *key, buffer_t *destination, const char **error_r)
{
- EVP_PKEY *pubkey = (EVP_PKEY*)key;
+ EVP_PKEY *pubkey = key->key;
unsigned char *tmp = NULL;
size_t dest_used = buffer_get_used_size(destination);
EC_KEY_set_conv_form(EVP_PKEY_get0_EC_KEY(key), POINT_CONVERSION_COMPRESSED);
}
- *key_r = (struct dcrypt_private_key *)key;
+ *key_r = i_new(struct dcrypt_private_key, 1);
+ (*key_r)->key = key;
+ (*key_r)->ref++;
return TRUE;
}
if (key == NULL)
return dcrypt_openssl_error(error_r);
- *key_r = (struct dcrypt_public_key *)key;
+ *key_r = i_new(struct dcrypt_public_key, 1);
+ (*key_r)->key = key;
+ (*key_r)->ref++;
return TRUE;
}
return ret;
}
- EVP_PKEY *pkey = (EVP_PKEY*)key;
+ EVP_PKEY *pkey = key->key;
BIO *key_out = BIO_new(BIO_s_mem());
if (key_out == NULL)
return dcrypt_openssl_error(error_r);
if (format == DCRYPT_FORMAT_DOVECOT)
return dcrypt_openssl_store_public_key_dovecot(key, destination, error_r);
- EVP_PKEY *pkey = (EVP_PKEY*)key;
+ EVP_PKEY *pkey = key->key;
BIO *key_out = BIO_new(BIO_s_mem());
if (key_out == NULL)
return dcrypt_openssl_error(error_r);
static
void dcrypt_openssl_private_to_public_key(struct dcrypt_private_key *priv_key, struct dcrypt_public_key **pub_key_r)
{
- EVP_PKEY *pkey = (EVP_PKEY*)priv_key;
+ EVP_PKEY *pkey = priv_key->key;
EVP_PKEY *pk;
- if (*pub_key_r == NULL) {
- pk = EVP_PKEY_new();
- i_assert(pk != NULL); /* we shouldn't get malloc() failures */
- } else
- pk = (EVP_PKEY*)*pub_key_r;
+ pk = EVP_PKEY_new();
+ i_assert(pk != NULL); /* we shouldn't get malloc() failures */
if (EVP_PKEY_base_id(pkey) == EVP_PKEY_RSA)
{
i_unreached();
}
- *pub_key_r = (struct dcrypt_public_key*)pk;
+ *pub_key_r = i_new(struct dcrypt_public_key, 1);
+ (*pub_key_r)->key = pk;
+ (*pub_key_r)->ref++;
}
static
}
static
-void dcrypt_openssl_free_public_key(struct dcrypt_public_key **key)
+void dcrypt_openssl_ref_public_key(struct dcrypt_public_key *key)
{
- EVP_PKEY_free((EVP_PKEY*)*key);
+ key->ref++;
+}
+static
+void dcrypt_openssl_ref_private_key(struct dcrypt_private_key *key)
+{
+ key->ref++;
+}
+static
+void dcrypt_openssl_unref_public_key(struct dcrypt_public_key **key)
+{
+ struct dcrypt_public_key *_key = *key;
*key = NULL;
+ if (--_key->ref > 0) return;
+ EVP_PKEY_free(_key->key);
+ i_free(_key);
}
static
-void dcrypt_openssl_free_private_key(struct dcrypt_private_key **key)
+void dcrypt_openssl_unref_private_key(struct dcrypt_private_key **key)
{
- EVP_PKEY_free((EVP_PKEY*)*key);
+ struct dcrypt_private_key *_key = *key;
*key = NULL;
+ if (--_key->ref > 0) return;
+ EVP_PKEY_free(_key->key);
+ i_free(_key);
}
static
-void dcrypt_openssl_free_keypair(struct dcrypt_keypair *keypair)
+void dcrypt_openssl_unref_keypair(struct dcrypt_keypair *keypair)
{
- dcrypt_openssl_free_public_key(&(keypair->pub));
- dcrypt_openssl_free_private_key(&(keypair->priv));
+ dcrypt_openssl_unref_public_key(&(keypair->pub));
+ dcrypt_openssl_unref_private_key(&(keypair->priv));
}
static
{
int ec;
- EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new((EVP_PKEY*)key, NULL);
- size_t outl = EVP_PKEY_size((EVP_PKEY*)key);
+ EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(key->key, NULL);
+ size_t outl = EVP_PKEY_size(key->key);
unsigned char buf[outl];
if (ctx == NULL ||
{
int ec;
- EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new((EVP_PKEY*)key, NULL);
- size_t outl = EVP_PKEY_size((EVP_PKEY*)key);
+ EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(key->key, NULL);
+ size_t outl = EVP_PKEY_size(key->key);
unsigned char buf[outl];
if (ctx == NULL ||
static
enum dcrypt_key_type dcrypt_openssl_private_key_type(struct dcrypt_private_key *key)
{
- EVP_PKEY *priv = (EVP_PKEY*)key;
+ EVP_PKEY *priv = key->key;
i_assert(priv != NULL);
if (EVP_PKEY_base_id(priv) == EVP_PKEY_RSA) return DCRYPT_KEY_RSA;
else if (EVP_PKEY_base_id(priv) == EVP_PKEY_EC) return DCRYPT_KEY_EC;
static
enum dcrypt_key_type dcrypt_openssl_public_key_type(struct dcrypt_public_key *key)
{
- EVP_PKEY *pub = (EVP_PKEY*)key;
+ EVP_PKEY *pub = key->key;
i_assert(pub != NULL);
if (EVP_PKEY_base_id(pub) == EVP_PKEY_RSA) return DCRYPT_KEY_RSA;
else if (EVP_PKEY_base_id(pub) == EVP_PKEY_EC) return DCRYPT_KEY_EC;
bool dcrypt_openssl_public_key_id_old(struct dcrypt_public_key *key, buffer_t *result, const char **error_r)
{
unsigned char buf[SHA256_DIGEST_LENGTH];
- EVP_PKEY *pub = (EVP_PKEY*)key;
+ EVP_PKEY *pub = key->key;
i_assert(pub != NULL);
if (EVP_PKEY_base_id(pub) != EVP_PKEY_EC) {
bool dcrypt_openssl_private_key_id_old(struct dcrypt_private_key *key, buffer_t *result, const char **error_r)
{
unsigned char buf[SHA256_DIGEST_LENGTH];
- EVP_PKEY *priv = (EVP_PKEY*)key;
+ EVP_PKEY *priv = key->key;
i_assert(priv != NULL);
if (EVP_PKEY_base_id(priv) != EVP_PKEY_EC) {
bool dcrypt_openssl_public_key_id(struct dcrypt_public_key *key, const char *algorithm, buffer_t *result, const char **error_r)
{
const EVP_MD *md = EVP_get_digestbyname(algorithm);
- EVP_PKEY *pub = (EVP_PKEY*)key;
+ EVP_PKEY *pub = key->key;
i_assert(pub != NULL);
if (md == NULL) {
bool dcrypt_openssl_private_key_id(struct dcrypt_private_key *key, const char *algorithm, buffer_t *result, const char **error_r)
{
const EVP_MD *md = EVP_get_digestbyname(algorithm);
- EVP_PKEY *priv = (EVP_PKEY*)key;
+ EVP_PKEY *priv = key->key;
i_assert(priv != NULL);
if (md == NULL) {
.store_public_key = dcrypt_openssl_store_public_key,
.private_to_public_key = dcrypt_openssl_private_to_public_key,
.key_string_get_info = dcrypt_openssl_key_string_get_info,
- .free_keypair = dcrypt_openssl_free_keypair,
- .free_public_key = dcrypt_openssl_free_public_key,
- .free_private_key = dcrypt_openssl_free_private_key,
+ .unref_keypair = dcrypt_openssl_unref_keypair,
+ .unref_public_key = dcrypt_openssl_unref_public_key,
+ .unref_private_key = dcrypt_openssl_unref_private_key,
+ .ref_public_key = dcrypt_openssl_ref_public_key,
+ .ref_private_key = dcrypt_openssl_ref_private_key,
.rsa_encrypt = dcrypt_openssl_rsa_encrypt,
.rsa_decrypt = dcrypt_openssl_rsa_decrypt,
.oid2name = dcrypt_openssl_oid2name,