ENGINE-84: working on ensuring keypairs missing private keys are not selected for encryption candidates

doc_update_sequoia
Krista Grothoff 7 years ago
parent c6aee70900
commit 123ba933e4

@ -47,7 +47,8 @@ PEP_STATUS init_cryptotech(PEP_SESSION session, bool in_first)
cryptotech[PEP_crypt_OpenPGP].key_expired = pgp_key_expired;
cryptotech[PEP_crypt_OpenPGP].key_revoked = pgp_key_revoked;
cryptotech[PEP_crypt_OpenPGP].key_created = pgp_key_created;
cryptotech[PEP_crypt_OpenPGP].pair_has_private = pgp_pair_has_private;
cryptotech[PEP_crypt_OpenPGP].contains_priv_key = pgp_contains_priv_key;
cryptotech[PEP_crypt_OpenPGP].find_private_keys = pgp_find_private_keys;
#ifdef PGP_BINARY_PATH
cryptotech[PEP_crypt_OpenPGP].binary_path = PGP_BINARY_PATH;
#endif

@ -72,9 +72,13 @@ typedef PEP_STATUS (*key_created_t)(PEP_SESSION session, const char *fpr,
typedef PEP_STATUS (*binary_path_t)(const char **path);
typedef PEP_STATUS (*pair_has_private_t)(PEP_SESSION session, const char *fpr,
typedef PEP_STATUS (*contains_priv_key_t)(PEP_SESSION session, const char *fpr,
bool *has_private);
typedef PEP_STATUS (*find_private_keys_t)(
PEP_SESSION session, const char *pattern, stringlist_t **keylist
);
typedef struct _PEP_cryptotech_t {
uint8_t id;
// the following are default values; comm_type may vary with key length or b0rken crypto
@ -97,7 +101,8 @@ typedef struct _PEP_cryptotech_t {
key_revoked_t key_revoked;
key_created_t key_created;
binary_path_t binary_path;
pair_has_private_t pair_has_private;
contains_priv_key_t contains_priv_key;
find_private_keys_t find_private_keys;
} PEP_cryptotech_t;
extern PEP_cryptotech_t cryptotech[PEP_crypt__count];

@ -313,7 +313,7 @@ PEP_STATUS elect_ownkey(
free(identity->fpr);
identity->fpr = NULL;
status = find_keys(session, identity->address, &keylist);
status = find_private_keys(session, identity->address, &keylist);
assert(status != PEP_OUT_OF_MEMORY);
if (status == PEP_OUT_OF_MEMORY)
return PEP_OUT_OF_MEMORY;
@ -378,6 +378,25 @@ PEP_STATUS elect_ownkey(
return PEP_STATUS_OK;
}
PEP_STATUS _has_usable_priv_key(PEP_SESSION session, char* fpr,
bool* is_usable) {
bool dont_use_fpr = true;
PEP_STATUS status = blacklist_is_listed(session, fpr, &dont_use_fpr);
if (!dont_use_fpr) {
// Make sure there is a *private* key associated with this fpr
bool has_private = false;
status = contains_priv_key(session, fpr, &has_private);
// TODO: check status
dont_use_fpr = !has_private;
}
*is_usable = !dont_use_fpr;
return status;
}
DYNAMIC_API PEP_STATUS myself(PEP_SESSION session, pEp_identity * identity)
{
pEp_identity *stored_identity;
@ -417,49 +436,73 @@ DYNAMIC_API PEP_STATUS myself(PEP_SESSION session, pEp_identity * identity)
assert(status != PEP_OUT_OF_MEMORY);
if (status == PEP_OUT_OF_MEMORY)
return PEP_OUT_OF_MEMORY;
bool dont_use_stored_fpr = true;
bool dont_use_input_fpr = true;
if (stored_identity)
{
if (EMPTYSTR(identity->fpr)) {
// First check to see if it's blacklisted?
char* stored_fpr = stored_identity->fpr;
bool has_private = false;
bool dont_use_fpr = false;
status = _has_usable_priv_key(session, stored_identity->fpr, &has_private);
status = blacklist_is_listed(session, stored_fpr, &dont_use_fpr);
if (!dont_use_fpr) {
// Make sure there is a *private* key associated with this fpr
}
identity->fpr = strdup(stored_identity->fpr);
assert(identity->fpr);
if (identity->fpr == NULL)
{
return PEP_OUT_OF_MEMORY;
if (has_private) {
identity->fpr = strdup(stored_identity->fpr);
assert(identity->fpr);
if (identity->fpr == NULL)
{
return PEP_OUT_OF_MEMORY;
}
dont_use_stored_fpr = false;
}
}
identity->flags = stored_identity->flags;
}
else if (!EMPTYSTR(identity->fpr))
if (dont_use_stored_fpr && !EMPTYSTR(identity->fpr))
{
// App must have a good reason to give fpr, such as explicit
// import of private key, or similar.
// Take given fpr as-is.
identity->flags = 0;
// BUT:
// First check to see if it's blacklisted or private part is missing?
bool has_private = false;
status = _has_usable_priv_key(session, identity->fpr, &has_private);
if (has_private) {
identity->flags = 0;
dont_use_input_fpr = false;
}
}
else
// Ok, we failed to get keys either way, so let's elect one.
if (dont_use_input_fpr && dont_use_stored_fpr)
{
status = elect_ownkey(session, identity);
assert(status == PEP_STATUS_OK);
if (status != PEP_STATUS_OK) {
return status;
}
identity->flags = 0;
// Check to see if it's blacklisted or private part is missing
bool has_private = false;
status = _has_usable_priv_key(session, identity->fpr, &has_private);
if (has_private) {
identity->flags = 0;
dont_use_input_fpr = false;
}
else { // OK, we've tried everything. Time to generate new keys.
}
}
bool revoked = false;
@ -844,3 +887,16 @@ the_end:
return status;
}
PEP_STATUS contains_priv_key(PEP_SESSION session, const char *fpr,
bool *has_private) {
assert(session);
assert(fpr);
assert(has_private);
if (!(session && fpr && has_private))
return PEP_ILLEGAL_VALUE;
return session->cryptotech[PEP_crypt_OpenPGP].contains_priv_key(session, fpr, has_private);
}

@ -185,6 +185,9 @@ DYNAMIC_API PEP_STATUS own_identities_retrieve(
identity_list **own_identities
);
PEP_STATUS contains_priv_key(PEP_SESSION session, const char *fpr,
bool *has_private);
#ifdef __cplusplus
}
#endif

@ -2107,6 +2107,16 @@ PEP_STATUS key_created(
created);
}
PEP_STATUS find_private_keys(PEP_SESSION session, const char* pattern,
stringlist_t **keylist) {
assert(session && pattern && keylist);
if (!(session && pattern && keylist))
return PEP_ILLEGAL_VALUE;
return session->cryptotech[PEP_crypt_OpenPGP].find_private_keys(session, pattern,
keylist);
}
DYNAMIC_API const char* get_engine_version() {
return PEP_ENGINE_VERSION;
}

@ -999,6 +999,20 @@ PEP_STATUS key_created(
);
// find_keys() - find keys in keyring
//
// parameters:
// session (in) session handle
// pattern (in) key id, user id or address to search for as
// UTF-8 string
// keylist (out) list of fingerprints found or NULL on error
//
// caveat:
// the ownerships of keylist isgoing to the caller
// the caller must use free_stringlist() to free it
PEP_STATUS find_private_keys(PEP_SESSION session, const char* pattern,
stringlist_t **keylist);
// get_engine_version() - returns the current version of pEpEngine (this is different
// from the pEp protocol version!)
//

@ -1411,61 +1411,61 @@ PEP_STATUS pgp_recv_key(PEP_SESSION session, const char *pattern)
return PEP_STATUS_OK;
}
PEP_STATUS pgp_find_keys(
PEP_SESSION session, const char *pattern, stringlist_t **keylist
)
{
static PEP_STATUS _pgp_search_keys(PEP_SESSION session, const char* pattern,
stringlist_t** keylist,
int private_only) {
gpgme_error_t gpgme_error;
gpgme_key_t key;
assert(session);
assert(pattern);
assert(keylist);
*keylist = NULL;
gpgme_error = gpg.gpgme_op_keylist_start(session->ctx, pattern, 0);
gpgme_error = gpg.gpgme_op_keylist_start(session->ctx, pattern, private_only);
gpgme_error = _GPGERR(gpgme_error);
switch (gpgme_error) {
case GPG_ERR_NO_ERROR:
break;
case GPG_ERR_INV_VALUE:
assert(0);
return PEP_UNKNOWN_ERROR;
default:
gpg.gpgme_op_keylist_end(session->ctx);
return PEP_GET_KEY_FAILED;
case GPG_ERR_NO_ERROR:
break;
case GPG_ERR_INV_VALUE:
assert(0);
return PEP_UNKNOWN_ERROR;
default:
gpg.gpgme_op_keylist_end(session->ctx);
return PEP_GET_KEY_FAILED;
};
stringlist_t *_keylist = new_stringlist(NULL);
stringlist_t *_k = _keylist;
do {
gpgme_error = gpg.gpgme_op_keylist_next(session->ctx, &key);
gpgme_error = _GPGERR(gpgme_error);
assert(gpgme_error != GPG_ERR_INV_VALUE);
switch (gpgme_error) {
case GPG_ERR_EOF:
break;
case GPG_ERR_NO_ERROR:
assert(key);
assert(key->subkeys);
char *fpr = key->subkeys->fpr;
assert(fpr);
_k = stringlist_add(_k, fpr);
assert(_k);
if (_k != NULL)
case GPG_ERR_EOF:
break;
case GPG_ERR_ENOMEM:
free_stringlist(_keylist);
gpg.gpgme_op_keylist_end(session->ctx);
return PEP_OUT_OF_MEMORY;
default:
gpg.gpgme_op_keylist_end(session->ctx);
return PEP_UNKNOWN_ERROR;
case GPG_ERR_NO_ERROR:
assert(key);
assert(key->subkeys);
char *fpr = key->subkeys->fpr;
assert(fpr);
_k = stringlist_add(_k, fpr);
assert(_k);
if (_k != NULL)
break;
case GPG_ERR_ENOMEM:
free_stringlist(_keylist);
gpg.gpgme_op_keylist_end(session->ctx);
return PEP_OUT_OF_MEMORY;
default:
gpg.gpgme_op_keylist_end(session->ctx);
return PEP_UNKNOWN_ERROR;
};
} while (gpgme_error != GPG_ERR_EOF);
gpg.gpgme_op_keylist_end(session->ctx);
if (_keylist->value == NULL) {
free_stringlist(_keylist);
@ -1475,6 +1475,20 @@ PEP_STATUS pgp_find_keys(
return PEP_STATUS_OK;
}
PEP_STATUS pgp_find_keys(
PEP_SESSION session, const char *pattern, stringlist_t **keylist
)
{
return _pgp_search_keys(session, pattern, keylist, 0);
}
PEP_STATUS pgp_find_private_keys(
PEP_SESSION session, const char *pattern, stringlist_t **keylist
)
{
return _pgp_search_keys(session, pattern, keylist, 1);
}
PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern)
{
gpgme_error_t gpgme_error;
@ -2118,11 +2132,11 @@ PEP_STATUS pgp_binary(const char **path)
return PEP_STATUS_OK;
}
PEP_STATUS pgp_pair_has_private(PEP_SESSION session, const char *fpr,
PEP_STATUS pgp_contains_priv_key(PEP_SESSION session, const char *fpr,
bool *has_private) {
status = PEP_STATUS_OK;
gpg_key_t output_key;
gpgme_error_t gpgerr = gpgme_get_key(session->ctx, fpr, &output_key, true);
PEP_STATUS status = PEP_STATUS_OK;
gpgme_key_t output_key;
gpgme_error_t gpgerr = gpg.gpgme_get_key(session->ctx, fpr, &output_key, true);
*has_private = false;
switch (gpgerr) {
case GPG_ERR_EOF:

@ -85,6 +85,15 @@ PEP_STATUS pgp_key_created(
time_t *created
);
PEP_STATUS pgp_contains_priv_key(
PEP_SESSION session,
const char *fpr,
bool *has_private);
PEP_STATUS pgp_find_private_keys(
PEP_SESSION session, const char *pattern, stringlist_t **keylist
);
PEP_STATUS pgp_binary(const char **path);
#define PGP_BINARY_PATH pgp_binary

Loading…
Cancel
Save