public key
----------
- 2<tab>HEX(i2d_PUBKEY)
+ 2<tab>HEX(i2d_PUBKEY)<tab>key id
- enctype none
2<tab>key algo oid<tab>0<tab>(RSA = i2d_PrivateKey, EC=Private Point)<tab>key id
static
bool dcrypt_openssl_generate_rsa_key(int bits, EVP_PKEY **key, const char **error_r)
{
+ i_assert(bits >= 256);
int ec = 0;
EVP_PKEY_CTX *ctx;
static
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;
BN_CTX *bn_ctx = BN_CTX_new();
if (bn_ctx == NULL)
return dcrypt_openssl_error(error_r);
}
EVP_PKEY_set1_EC_KEY(peer, ec_key);
+ EC_KEY_free(ec_key);
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(local, NULL);
/* initialize derivation */
EVP_PKEY_derive_init(pctx) != 1 ||
EVP_PKEY_derive_set_peer(pctx, peer) != 1) {
EVP_PKEY_CTX_free(pctx);
- EC_KEY_free(ec_key);
+ EVP_PKEY_free(peer);
return dcrypt_openssl_error(error_r);
}
size_t len;
if (EVP_PKEY_derive(pctx, NULL, &len) != 1) {
EVP_PKEY_CTX_free(pctx);
- EC_KEY_free(ec_key);
+ EVP_PKEY_free(peer);
return dcrypt_openssl_error(error_r);
}
unsigned char buf[len];
memset(buf,0,len);
if (EVP_PKEY_derive(pctx, buf, &len) != 1) {
EVP_PKEY_CTX_free(pctx);
- EC_KEY_free(ec_key);
+ EVP_PKEY_free(peer);
return dcrypt_openssl_error(error_r);
}
EVP_PKEY_CTX_free(pctx);
buffer_append(S, buf, len);
- EC_KEY_free(ec_key);
EVP_PKEY_free(peer);
return TRUE;
}
const char **error_r)
{
int nid, ec, enctype;
- EC_KEY *eckey = NULL;
BIGNUM *point = NULL;
if (str_to_int(input[1], &nid) != 0) {
return FALSE;
}
- eckey = EC_KEY_new_by_curve_name(nid);
- if (eckey == NULL) return dcrypt_openssl_error(error_r);
-
/* decode and optionally decipher private key value */
if (enctype == DCRYPT_DOVECOT_KEY_ENCRYPT_NONE) {
point = BN_new();
if (point == NULL || BN_hex2bn(&point, input[3]) < 1) {
BN_free(point);
- EC_KEY_free(eckey);
return dcrypt_openssl_error(error_r);
}
} else if (enctype == DCRYPT_DOVECOT_KEY_ENCRYPT_PASSWORD) {
const char *enc_priv_pt = input[3];
const char *salt = input[4];
if (!dcrypt_openssl_decrypt_point_password_v1(enc_priv_pt, password, salt, &point, error_r)) {
- EC_KEY_free(eckey);
return FALSE;
}
} else if (enctype == DCRYPT_DOVECOT_KEY_ENCRYPT_PK) {
/* by key */
const char *enc_priv_pt = input[3];
const char *peer_key = input[4];
+ i_assert(dec_key != NULL);
if (!dcrypt_openssl_decrypt_point_ec_v1(dec_key, enc_priv_pt, peer_key, &point, error_r)) {
- EC_KEY_free(eckey);
return FALSE;
}
} else {
if (error_r != NULL)
*error_r = "Invalid key data";
- EC_KEY_free(eckey);
return FALSE;
}
+ EC_KEY *eckey = EC_KEY_new_by_curve_name(nid);
+ if (eckey == NULL) return dcrypt_openssl_error(error_r);
+
/* assign private key */
BN_CTX *bnctx = BN_CTX_new();
if (bnctx == NULL) {
return dcrypt_openssl_error(error_r);
}
EVP_PKEY_set1_RSA(pkey, rsa);
+ RSA_free(rsa);
*key_r = (struct dcrypt_private_key *)pkey;
} else {
int ec;
int len, const char **input, const char **error_r)
{
int nid;
- if (len != 3) {
+ if (len != 4) {
if (error_r != NULL)
*error_r = "Corrupted data";
return -1;
EC_POINT *point = EC_POINT_new(EC_KEY_get0_group(eckey));
if (bnctx == NULL || point == NULL ||
EC_POINT_hex2point(EC_KEY_get0_group(eckey),
- input[2], point, bnctx) == NULL) {
+ input[2], point, bnctx) == NULL) {
BN_CTX_free(bnctx);
EC_KEY_free(eckey);
EC_POINT_free(point);
if (EC_KEY_check_key(eckey) == 1) {
EVP_PKEY *key = EVP_PKEY_new();
EVP_PKEY_set1_EC_KEY(key, eckey);
+ 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);
+ 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;
return 0;
}
int dcrypt_openssl_load_public_key_dovecot_v2(struct dcrypt_public_key **key_r,
int len, const char **input, const char **error_r)
{
- if (len != 2 || strlen(input[1]) < 2 || (strlen(input[1])%2) != 0) {
+ if (len != 3 || strlen(input[1]) < 2 || (strlen(input[1])%2) != 0) {
if (error_r != NULL)
*error_r = "Corrupted data";
return -1;
return -1;
}
+ /* 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);
+ 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(pkey);
+ return -1;
+ }
+
*key_r = (struct dcrypt_public_key *)pkey;
return 0;
}
{
EVP_PKEY *pubkey = (EVP_PKEY*)key;
unsigned char *tmp = NULL;
+ size_t dest_used = buffer_get_used_size(destination);
int rv = i2d_PUBKEY(pubkey, &tmp);
if (tmp == NULL)
return dcrypt_openssl_error(error_r);
+
/* then store it */
str_append_c(destination, '2');
str_append_c(destination, '\t');
binary_to_hex_append(destination, tmp, rv);
OPENSSL_free(tmp);
+ /* append public key ID */
+ str_append_c(destination, '\t');
+
+ buffer_t *buf = buffer_create_dynamic(pool_datastack_create(), 32);
+ bool res = dcrypt_openssl_public_key_id(key, "sha256", buf, error_r);
+
+ if (!res) {
+ buffer_set_used_size(destination, dest_used);
+ return FALSE;
+ }
+
+ str_append(destination, binary_to_hex(buf->data, buf->used));
return TRUE;
}
EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE);
key = EVP_PKEY_new();
- if (key == NULL)
- EC_KEY_free(eckey);
- else
+ if (key != NULL)
EVP_PKEY_set1_EC_KEY(key, eckey);
+ EC_KEY_free(eckey);
}
}
if (EVP_PKEY_base_id(pkey) == EVP_PKEY_RSA)
{
- EVP_PKEY_set1_RSA(pk, RSAPublicKey_dup(EVP_PKEY_get0_RSA(pkey)));
+ RSA *rsa = RSAPublicKey_dup(EVP_PKEY_get0_RSA(pkey));
+ EVP_PKEY_set1_RSA(pk, rsa);
+ RSA_free(rsa);
} else if (EVP_PKEY_base_id(pkey) == EVP_PKEY_EC) {
EC_KEY* eck = EVP_PKEY_get1_EC_KEY(pkey);
EC_KEY_set_asn1_flag(eck, OPENSSL_EC_NAMED_CURVE);
/* field 1 - version */
if (strcmp(fields[0], "1") == 0) {
version = DCRYPT_KEY_VERSION_1;
- if (nfields == 3) {
+ if (nfields == 4) {
kind = DCRYPT_KEY_KIND_PUBLIC;
} else if (nfields == 5 && strcmp(fields[2],"0") == 0) {
kind = DCRYPT_KEY_KIND_PRIVATE;
} else if (nfields == 6 && strcmp(fields[2],"2") == 0) {
kind = DCRYPT_KEY_KIND_PRIVATE;
encryption_type = DCRYPT_KEY_ENCRYPTION_TYPE_PASSWORD;
- } else if (nfields == 11 && strcmp(fields[2],"1") == 0) {
+ } else if (nfields == 7 && strcmp(fields[2],"1") == 0) {
kind = DCRYPT_KEY_KIND_PRIVATE;
encryption_type = DCRYPT_KEY_ENCRYPTION_TYPE_KEY;
if (encryption_key_hash_r != NULL)
}
} else if (strcmp(fields[0], "2") == 0) {
version = DCRYPT_KEY_VERSION_1;
- if (nfields == 2) {
+ if (nfields == 3) {
kind = DCRYPT_KEY_KIND_PUBLIC;
} else if (nfields == 5 && strcmp(fields[2],"0") == 0) {
kind = DCRYPT_KEY_KIND_PRIVATE;