char *key_id;
};
-#define DCRYPT_SET_ERROR(error) STMT_START { if (error_r != NULL) *error_r = (error); } STMT_END
-
static bool
dcrypt_openssl_public_key_id(struct dcrypt_public_key *key,
const char *algorithm, buffer_t *result,
i_fatal_status(FATAL_OUTOFMEM, "OpenSSL malloc() failed");
if (ERR_peek_error() == 0)
break;
- if (error_r == NULL)
- continue;
if (errstr == NULL)
errstr = t_str_new(128);
else
str_append(errstr, ", ");
str_append(errstr, ssl_err2str(err, data, flags));
}
- if (error_r == NULL)
- return FALSE;
if (err == 0) {
if (errno != 0)
final_error = strerror(errno);
case DCRYPT_PADDING_RSA_NO:
return RSA_NO_PADDING;
default:
- DCRYPT_SET_ERROR("Unsupported padding mode");
+ *error_r = "Unsupported padding mode";
return -1;
}
i_unreached();
cipher = EVP_get_cipherbyname(algorithm);
if (cipher == NULL) {
- DCRYPT_SET_ERROR(t_strdup_printf("Invalid cipher %s",
- algorithm));
+ *error_r = t_strdup_printf("Invalid cipher %s",
+ algorithm);
return FALSE;
}
}
if (ec == 0)
- DCRYPT_SET_ERROR("data authentication failed");
+ *error_r = "data authentication failed";
else if (ec < 0)
dcrypt_openssl_error(error_r);
md = EVP_get_digestbyname(algorithm);
if(md == NULL) {
- DCRYPT_SET_ERROR(t_strdup_printf("Invalid digest %s",
- algorithm));
+ *error_r = t_strdup_printf("Invalid digest %s",
+ algorithm);
return FALSE;
}
EVP_PKEY *local = NULL;
EVP_PKEY *peer = peer_key->key;
if (EVP_PKEY_base_id(peer) != EVP_PKEY_EC) {
- DCRYPT_SET_ERROR("Only ECC key can be used");
+ *error_r = "Only ECC key can be used";
return FALSE;
}
/* determine MD */
const EVP_MD* md = EVP_get_digestbyname(hash);
if (md == NULL) {
- DCRYPT_SET_ERROR(t_strdup_printf("Invalid digest %s", hash));
+ *error_r = t_strdup_printf("Invalid digest %s", hash);
return FALSE;
}
} else if (kind == DCRYPT_KEY_EC) {
int nid = OBJ_sn2nid(curve);
if (nid == NID_undef) {
- DCRYPT_SET_ERROR(t_strdup_printf("Unknown EC curve %s",
- curve));
+ *error_r = t_strdup_printf("Unknown EC curve %s",
+ curve);
return FALSE;
}
if (dcrypt_openssl_generate_ec_key(nid, &pkey, error_r)) {
return dcrypt_openssl_error(error_r);
}
}
- DCRYPT_SET_ERROR("Key type not supported in this build");
+ *error_r = "Key type not supported in this build";
return FALSE;
}
BIGNUM *point = NULL;
if (str_to_int(input[1], &nid) != 0) {
- DCRYPT_SET_ERROR("Corrupted data");
+ *error_r = "Corrupted data";
return FALSE;
}
if (str_to_int(input[2], &enctype) != 0) {
- DCRYPT_SET_ERROR("Corrupted data");
+ *error_r = "Corrupted data";
return FALSE;
}
} else if (enctype == DCRYPT_DOVECOT_KEY_ENCRYPT_PASSWORD) {
/* by password */
if (password == NULL) {
- DCRYPT_SET_ERROR("password missing");
+ *error_r = "password missing";
return FALSE;
}
const char *enc_priv_pt = input[3];
} else if (enctype == DCRYPT_DOVECOT_KEY_ENCRYPT_PK) {
/* by key */
if (dec_key == NULL) {
- DCRYPT_SET_ERROR("decrypt key missing");
+ *error_r = "decrypt key missing";
return FALSE;
}
const char *enc_priv_pt = input[3];
return FALSE;
}
} else {
- DCRYPT_SET_ERROR("Invalid key data");
+ *error_r = "Invalid key data";
return FALSE;
}
const char *digest_hex =
binary_to_hex(digest, SHA256_DIGEST_LENGTH);
if (strcmp(digest_hex, input[len-1]) != 0) {
- DCRYPT_SET_ERROR("Key id mismatch after load");
+ *error_r = "Key id mismatch after load";
EC_KEY_free(eckey);
return FALSE;
}
/* check for encryption type */
if (str_to_int(input[2], &enctype) != 0) {
- DCRYPT_SET_ERROR("Corrupted data");
+ *error_r = "Corrupted data";
return FALSE;
}
if (enctype < 0 || enctype > 2) {
- DCRYPT_SET_ERROR("Corrupted data");
+ *error_r = "Corrupted data";
return FALSE;
}
if ((enctype == DCRYPT_DOVECOT_KEY_ENCRYPT_NONE && len != 5) ||
(enctype == DCRYPT_DOVECOT_KEY_ENCRYPT_PASSWORD && len != 9) ||
(enctype == DCRYPT_DOVECOT_KEY_ENCRYPT_PK && len != 11)) {
- DCRYPT_SET_ERROR("Corrupted data");
+ *error_r = "Corrupted data";
return FALSE;
}
/* decode and possibly decipher private key value */
if (enctype == DCRYPT_DOVECOT_KEY_ENCRYPT_NONE) {
if (hex_to_binary(input[3], key_data) != 0) {
- DCRYPT_SET_ERROR("Corrupted data");
+ *error_r = "Corrupted data";
}
} else if (enctype == DCRYPT_DOVECOT_KEY_ENCRYPT_PK) {
if (dec_key == NULL) {
- DCRYPT_SET_ERROR("decrypt key missing");
+ *error_r = "decrypt key missing";
return FALSE;
}
unsigned int rounds;
struct dcrypt_public_key *pubkey = NULL;
if (str_to_uint(input[6], &rounds) != 0) {
- DCRYPT_SET_ERROR("Corrupted data");
+ *error_r = "Corrupted data";
return FALSE;
}
if (strcmp(binary_to_hex(data->data, data->used),
input[9]) != 0) {
- DCRYPT_SET_ERROR("No private key available");
+ *error_r = "No private key available";
return FALSE;
}
}
} else if (enctype == DCRYPT_DOVECOT_KEY_ENCRYPT_PASSWORD) {
if (password == NULL) {
- DCRYPT_SET_ERROR("password missing");
+ *error_r = "password missing";
return FALSE;
}
unsigned int rounds;
if (str_to_uint(input[6], &rounds) != 0) {
- DCRYPT_SET_ERROR("Corrupted data");
+ *error_r = "Corrupted data";
return FALSE;
}
data = t_buffer_create(strlen(input[7])/2);
if (hex_to_binary(input[4], salt) != 0 ||
hex_to_binary(input[7], data) != 0) {
- DCRYPT_SET_ERROR("Corrupted data");
+ *error_r = "Corrupted data";
return FALSE;
}
if (strcmp(binary_to_hex(key_data->data, key_data->used),
input[len-1]) != 0) {
dcrypt_openssl_unref_private_key(key_r);
- DCRYPT_SET_ERROR("Key id mismatch after load");
+ *error_r = "Key id mismatch after load";
return FALSE;
}
if ((node = json_tree_find_key(root, "crv")) == NULL ||
(crv = json_tree_get_value_str(node)) == NULL) {
- DCRYPT_SET_ERROR("Missing crv parameter");
+ *error_r = "Missing crv parameter";
return FALSE;
}
if ((node = json_tree_find_key(root, "x")) == NULL ||
(x = json_tree_get_value_str(node)) == NULL) {
- DCRYPT_SET_ERROR("Missing x parameter");
+ *error_r = "Missing x parameter";
return FALSE;
}
if ((node = json_tree_find_key(root, "y")) == NULL ||
(y = json_tree_get_value_str(node)) == NULL) {
- DCRYPT_SET_ERROR("Missing y parameter");
+ *error_r = "Missing y parameter";
return FALSE;
}
if ((node = json_tree_find_key(root, "d")) == NULL ||
(d = json_tree_get_value_str(node)) == NULL) {
if (want_private_key) {
- DCRYPT_SET_ERROR("Missing d parameter");
+ *error_r = "Missing d parameter";
return FALSE;
}
}
/* determine NID */
int nid = jwk_curve_to_nid(crv);
if (nid == 0) {
- DCRYPT_SET_ERROR(t_strdup_printf("Unsupported curve: %s", crv));
+ *error_r = t_strdup_printf("Unsupported curve: %s", crv);
return FALSE;
}
/* create key */
EC_KEY *ec_key = EC_KEY_new_by_curve_name(nid);
if (ec_key == NULL) {
- DCRYPT_SET_ERROR("Cannot allocate memory");
+ *error_r = "Cannot allocate memory";
return FALSE;
}
/* n and e must be present */
if ((node = json_tree_find_key(root, "n")) == NULL ||
(n = json_tree_get_value_str(node)) == NULL) {
- DCRYPT_SET_ERROR("Missing n parameter");
+ *error_r = "Missing n parameter";
return FALSE;
}
if ((node = json_tree_find_key(root, "e")) == NULL ||
(e = json_tree_get_value_str(node)) == NULL) {
- DCRYPT_SET_ERROR("Missing e parameter");
+ *error_r = "Missing e parameter";
return FALSE;
}
if (want_private_key) {
if ((node = json_tree_find_key(root, "d")) == NULL ||
(d = json_tree_get_value_str(node)) == NULL) {
- DCRYPT_SET_ERROR("Missing d parameter");
+ *error_r = "Missing d parameter";
return FALSE;
}
if ((node = json_tree_find_key(root, "p")) == NULL ||
(p = json_tree_get_value_str(node)) == NULL) {
- DCRYPT_SET_ERROR("Missing p parameter");
+ *error_r = "Missing p parameter";
return FALSE;
}
if ((node = json_tree_find_key(root, "q")) == NULL ||
(q = json_tree_get_value_str(node)) == NULL) {
- DCRYPT_SET_ERROR("Missing q parameter");
+ *error_r = "Missing q parameter";
return FALSE;
}
if ((node = json_tree_find_key(root, "dp")) == NULL ||
(dp = json_tree_get_value_str(node)) == NULL) {
- DCRYPT_SET_ERROR("Missing dp parameter");
+ *error_r = "Missing dp parameter";
return FALSE;
}
if ((node = json_tree_find_key(root, "dq")) == NULL ||
(dq = json_tree_get_value_str(node)) == NULL) {
- DCRYPT_SET_ERROR("Missing dq parameter");
+ *error_r = "Missing dq parameter";
return FALSE;
}
if ((node = json_tree_find_key(root, "qi")) == NULL ||
(qi = json_tree_get_value_str(node)) == NULL) {
- DCRYPT_SET_ERROR("Missing qi parameter");
+ *error_r = "Missing qi parameter";
return FALSE;
}
}
bool ret;
if (parse_jwk_key(data, &key_tree, &error) != 0) {
- DCRYPT_SET_ERROR(t_strdup_printf("Cannot load JWK private key: %s",
- error));
+ *error_r = t_strdup_printf("Cannot load JWK private key: %s",
+ error);
return FALSE;
}
/* check key type */
if ((node = json_tree_find_key(root, "kty")) == NULL) {
- DCRYPT_SET_ERROR("Cannot load JWK private key: no kty parameter");
+ *error_r = "Cannot load JWK private key: no kty parameter";
json_tree_deinit(&key_tree);
return FALSE;
}
i_assert(ret || error != NULL);
if (!ret)
- DCRYPT_SET_ERROR(t_strdup_printf("Cannot load JWK private key: %s", error));
+ *error_r = t_strdup_printf("Cannot load JWK private key: %s", error);
else if (ret) {
*key_r = i_new(struct dcrypt_private_key, 1);
(*key_r)->key = pkey;
bool ret;
if (parse_jwk_key(data, &key_tree, &error) != 0) {
- DCRYPT_SET_ERROR(t_strdup_printf("Cannot load JWK public key: %s",
- error));
+ *error_r = t_strdup_printf("Cannot load JWK public key: %s",
+ error);
return FALSE;
}
/* check key type */
if ((node = json_tree_find_key(root, "kty")) == NULL) {
- DCRYPT_SET_ERROR("Cannot load JWK public key: no kty parameter");
+ *error_r = "Cannot load JWK public key: no kty parameter";
json_tree_deinit(&key_tree);
return FALSE;
}
i_assert(ret || error != NULL);
if (!ret)
- DCRYPT_SET_ERROR(t_strdup_printf("Cannot load JWK public key: %s", error));
+ *error_r = t_strdup_printf("Cannot load JWK public key: %s", error);
else if (ret) {
*key_r = i_new(struct dcrypt_public_key, 1);
(*key_r)->key = pkey;
if (is_private_key) {
const BIGNUM *d = EC_KEY_get0_private_key(ec_key);
if (d == NULL) {
- DCRYPT_SET_ERROR("No private key available");
+ *error_r = "No private key available";
return FALSE;
}
str_append(temp, "\",\"d\":\"");
return store_jwk_ec_key(pkey, is_private_key, usage, key_id,
cipher, password, enc_key, dest, error_r);
}
- DCRYPT_SET_ERROR("Unsupported key type");
+ *error_r = "Unsupported key type";
return FALSE;
}
{
int nid;
if (str_to_int(input[1], &nid) != 0) {
- DCRYPT_SET_ERROR("Corrupted data");
+ *error_r = "Corrupted data";
return FALSE;
}
}
if (strcmp(binary_to_hex(dgst->data, dgst->used),
input[len-1]) != 0) {
- DCRYPT_SET_ERROR("Key id mismatch after load");
+ *error_r = "Key id mismatch after load";
EVP_PKEY_free(key);
return FALSE;
}
return FALSE;
}
if (strcmp(binary_to_hex(dgst->data, dgst->used), input[len-1]) != 0) {
- DCRYPT_SET_ERROR("Key id mismatch after load");
+ *error_r = "Key id mismatch after load";
EVP_PKEY_free(pkey);
return FALSE;
}
if (len < 1)
return dcrypt_openssl_error(error_r);
if (len > (int)sizeof(objtxt)) {
- DCRYPT_SET_ERROR("Object identifier too long");
+ *error_r = "Object identifier too long";
return FALSE;
}
return FALSE;
}
if (kind != DCRYPT_KEY_KIND_PRIVATE) {
- DCRYPT_SET_ERROR("key is not private");
+ *error_r = "key is not private";
return FALSE;
}
}
/* JWK private keys can be loaded as public */
if (kind != DCRYPT_KEY_KIND_PUBLIC && format != DCRYPT_FORMAT_JWK) {
- DCRYPT_SET_ERROR("key is not public");
+ *error_r = "key is not public";
return FALSE;
}
return dcrypt_openssl_error(error_r);
}
if (strcmp(buf, "-----BEGIN PUBLIC KEY-----") != 0) {
- DCRYPT_SET_ERROR("Missing public key header");
+ *error_r = "Missing public key header";
return FALSE;
}
BIO *b64 = BIO_new(BIO_f_base64());
if (cipher != NULL) {
algo = EVP_get_cipherbyname(cipher);
if (algo == NULL) {
- DCRYPT_SET_ERROR(t_strdup_printf("Invalid cipher %s",
- cipher));
+ *error_r = t_strdup_printf("Invalid cipher %s", cipher);
return FALSE;
}
}
format = DCRYPT_FORMAT_PEM;
version = DCRYPT_KEY_VERSION_NA;
if (str_begins_with(key_data, "RSA ")) {
- DCRYPT_SET_ERROR("RSA private key format not supported, convert it to PKEY format with openssl pkey");
+ *error_r = "RSA private key format not supported, convert it to PKEY format with openssl pkey";
return FALSE;
}
if (str_begins(key_data, "ENCRYPTED ", &key_data))
else if (str_begins_with(key_data, "PUBLIC KEY-----"))
kind = DCRYPT_KEY_KIND_PUBLIC;
else {
- DCRYPT_SET_ERROR("Unknown/invalid PEM key type");
+ *error_r = "Unknown/invalid PEM key type";
return FALSE;
}
} else if (*key_data == '{') {
const struct json_tree_node *root, *node;
const char *value, *error;
if (parse_jwk_key(key_data, &tree, &error) != 0) {
- DCRYPT_SET_ERROR("Unknown/invalid key data");
+ *error_r = "Unknown/invalid key data";
return FALSE;
}
if ((node = json_tree_find_key(root, "kty")) == NULL ||
(value = json_tree_get_value_str(node)) == NULL) {
json_tree_deinit(&tree);
- DCRYPT_SET_ERROR("Invalid JWK key: Missing kty parameter");
+ *error_r = "Invalid JWK key: Missing kty parameter";
return FALSE;
} else if (strcmp(value, "RSA") == 0) {
if (json_tree_find_key(root, "d") != NULL)
kind = DCRYPT_KEY_KIND_PUBLIC;
} else {
json_tree_deinit(&tree);
- DCRYPT_SET_ERROR("Unsupported JWK key type");
+ *error_r = "Unsupported JWK key type";
return FALSE;
}
json_tree_deinit(&tree);
} else {
if (str_begins_with(key_data, "1:")) {
- DCRYPT_SET_ERROR("Dovecot v1 key format uses tab to separate fields");
+ *error_r = "Dovecot v1 key format uses tab to separate fields";
return FALSE;
} else if (str_begins_with(key_data, "2\t")) {
- DCRYPT_SET_ERROR("Dovecot v2 key format uses colon to separate fields");
+ *error_r = "Dovecot v2 key format uses colon to separate fields";
return FALSE;
}
const char **fields = t_strsplit(key_data, ":\t");
int nfields = str_array_length(fields);
if (nfields < 2) {
- DCRYPT_SET_ERROR("Unknown key format");
+ *error_r = "Unknown key format";
return FALSE;
}
if (encryption_key_hash_r != NULL)
encryption_key_hash = i_strdup(fields[nfields-2]);
} else {
- DCRYPT_SET_ERROR("Invalid dovecot v1 encoding");
+ *error_r = "Invalid dovecot v1 encoding";
return FALSE;
}
} else if (strcmp(fields[0], "2") == 0) {
if (encryption_key_hash_r != NULL)
encryption_key_hash = i_strdup(fields[nfields-2]);
} else {
- DCRYPT_SET_ERROR("Invalid dovecot v2 encoding");
+ *error_r = "Invalid dovecot v2 encoding";
return FALSE;
}
} else {
- DCRYPT_SET_ERROR("Invalid dovecot key version");
+ *error_r = "Invalid dovecot key version";
return FALSE;
}
size_t len = OBJ_length(obj);
if (len == 0)
{
- DCRYPT_SET_ERROR("Object has no OID assigned");
+ *error_r = "Object has no OID assigned";
return FALSE;
}
len = i2d_ASN1_OBJECT(obj, NULL);
EVP_PKEY *pub = key->key;
if (EVP_PKEY_base_id(pub) != EVP_PKEY_EC) {
- DCRYPT_SET_ERROR("Only EC key supported");
+ *error_r = "Only EC key supported";
return FALSE;
}
EVP_PKEY *priv = key->key;
if (EVP_PKEY_base_id(priv) != EVP_PKEY_EC) {
- DCRYPT_SET_ERROR("Only EC key supported");
+ *error_r = "Only EC key supported";
return FALSE;
}
EVP_PKEY *pub = key->key;
if (md == NULL) {
- DCRYPT_SET_ERROR(t_strdup_printf("Unknown cipher %s", algorithm));
+ *error_r = t_strdup_printf("Unknown cipher %s", algorithm);
return FALSE;
}
EVP_PKEY *priv = key->key;
if (md == NULL) {
- DCRYPT_SET_ERROR(t_strdup_printf("Unknown cipher %s", algorithm));
+ *error_r = t_strdup_printf("Unknown cipher %s", algorithm);
return FALSE;
}
break;
case DCRYPT_SIGNATURE_FORMAT_X962:
if (EVP_PKEY_base_id(key->key) == EVP_PKEY_RSA) {
- DCRYPT_SET_ERROR("Format does not support RSA");
+ *error_r = "Format does not support RSA";
return FALSE;
}
return dcrypt_openssl_sign_ecdsa(key, algorithm,
return FALSE;
if (md == NULL) {
- DCRYPT_SET_ERROR(t_strdup_printf("Unknown digest %s", algorithm));
+ *error_r = t_strdup_printf("Unknown digest %s", algorithm);
return FALSE;
}
bool *valid_r, const char **error_r)
{
if ((signature_len % 2) != 0) {
- DCRYPT_SET_ERROR("Truncated signature");
+ *error_r = "Truncated signature";
return FALSE;
}
break;
case DCRYPT_SIGNATURE_FORMAT_X962:
if (EVP_PKEY_base_id(key->key) == EVP_PKEY_RSA) {
- DCRYPT_SET_ERROR("Format does not support RSA");
+ *error_r = "Format does not support RSA";
return FALSE;
}
return dcrypt_openssl_verify_ecdsa(key, algorithm,
return FALSE;
if (md == NULL) {
- DCRYPT_SET_ERROR(t_strdup_printf("Unknown digest %s", algorithm));
+ *error_r = t_strdup_printf("Unknown digest %s", algorithm);
return FALSE;
}
t_array_init(&keys, 2);
if (EVP_PKEY_base_id(priv) == EVP_PKEY_RSA) {
- DCRYPT_SET_ERROR("Not implemented");
+ *error_r = "Not implemented";
return FALSE;
} else if (EVP_PKEY_base_id(priv) == EVP_PKEY_EC) {
/* store OID */
ASN1_OBJECT *obj = OBJ_nid2obj(nid);
int len = OBJ_length(obj);
if (len == 0) {
- DCRYPT_SET_ERROR("Object has no OID assigned");
+ *error_r = "Object has no OID assigned";
return FALSE;
}
len = i2d_ASN1_OBJECT(obj, NULL);
item->len = len;
*type_r = DCRYPT_KEY_EC;
} else {
- DCRYPT_SET_ERROR("Key type unsupported");
+ *error_r = "Key type unsupported";
return FALSE;
}
t_array_init(&keys, 2);
if (EVP_PKEY_base_id(pub) == EVP_PKEY_RSA) {
- DCRYPT_SET_ERROR("Not implemented");
+ *error_r = "Not implemented";
return FALSE;
} else if (EVP_PKEY_base_id(pub) == EVP_PKEY_EC) {
/* store OID */
ASN1_OBJECT *obj = OBJ_nid2obj(nid);
int len = OBJ_length(obj);
if (len == 0) {
- DCRYPT_SET_ERROR("Object has no OID assigned");
+ *error_r = "Object has no OID assigned";
return FALSE;
}
len = i2d_ASN1_OBJECT(obj, NULL);
return dcrypt_openssl_error(error_r);
*type_r = DCRYPT_KEY_EC;
} else {
- DCRYPT_SET_ERROR("Key type unsupported");
+ *error_r = "Key type unsupported";
return FALSE;
}
const struct dcrypt_raw_key *item;
if (type == DCRYPT_KEY_RSA) {
- DCRYPT_SET_ERROR("Not implemented");
+ *error_r = "Not implemented";
return FALSE;
} else if (type == DCRYPT_KEY_EC) {
/* get curve */
if (array_count(keys) < 2) {
- DCRYPT_SET_ERROR("Invalid parameters");
+ *error_r = "Invalid parameters";
return FALSE;
}
item = array_idx(keys, 0);
(*key_r)->ref++;
return TRUE;
} else {
- DCRYPT_SET_ERROR("Key type unsupported");
+ *error_r = "Key type unsupported";
}
return FALSE;
const struct dcrypt_raw_key *item;
if (type == DCRYPT_KEY_RSA) {
- DCRYPT_SET_ERROR("Not implemented");
+ *error_r = "Not implemented";
return FALSE;
} else if (type == DCRYPT_KEY_EC) {
/* get curve */
if (array_count(keys) < 2) {
- DCRYPT_SET_ERROR("Invalid parameters");
+ *error_r = "Invalid parameters";
return FALSE;
}
item = array_idx(keys, 0);
(*key_r)->ref++;
return TRUE;
} else {
- DCRYPT_SET_ERROR("Key type unsupported");
+ *error_r = "Key type unsupported";
}
return FALSE;
char objtxt[OID_TEXT_MAX_LEN];
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) {
- DCRYPT_SET_ERROR("Unsupported key type");
+ *error_r = "Unsupported key type";
return FALSE;
}
if (len < 1) {
return dcrypt_openssl_error(error_r);
} else if ((unsigned int)len > sizeof(objtxt)) {
- DCRYPT_SET_ERROR("Object name too long");
+ *error_r = "Object name too long";
return FALSE;
}