Skip to content

Commit

Permalink
Refactor pgp_key_search_t and related types to C++.
Browse files Browse the repository at this point in the history
  • Loading branch information
ni4 authored and ronaldtse committed Mar 18, 2024
1 parent 4a835bb commit 7165af6
Show file tree
Hide file tree
Showing 12 changed files with 453 additions and 428 deletions.
2 changes: 1 addition & 1 deletion include/rekey/rnp_key_store.h
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ class KeyStore {
*/
pgp_key_t *primary_key(const pgp_key_t &subkey);

pgp_key_t *search(const pgp_key_search_t &search, pgp_key_t *after = nullptr);
pgp_key_t *search(const KeySearch &search, pgp_key_t *after = nullptr);
};
} // namespace rnp

Expand Down
22 changes: 22 additions & 0 deletions src/lib/crypto/mem.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#elif defined(CRYPTO_BACKEND_OPENSSL)
#include <openssl/crypto.h>
#endif
#include "str-utils.h"

namespace rnp {

Expand Down Expand Up @@ -159,6 +160,27 @@ bool hex_encode(const uint8_t *buf,
HexFormat format = HexFormat::Uppercase);
size_t hex_decode(const char *hex, uint8_t *buf, size_t buf_len);

inline std::string
bin_to_hex(const uint8_t *data, size_t len, HexFormat format = rnp::HexFormat::Uppercase)
{
std::string res(len * 2 + 1, '\0');
hex_encode(data, len, &res.front(), res.size(), format);
return res;
}

inline std::vector<uint8_t>
hex_to_bin(const std::string &str)
{
if (str.empty() || !rnp::is_hex(str)) {
return {};
}
/* 1 extra char for case of non-even input , 1 for terminating zero */
std::vector<uint8_t> res(str.size() / 2 + 2);
size_t len = rnp::hex_decode(str.c_str(), res.data(), res.size());
res.resize(len);
return res;
}

} // namespace rnp

void secure_clear(void *vp, size_t size);
Expand Down
22 changes: 18 additions & 4 deletions src/lib/ffi-priv-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <json.h>
#include "utils.h"
#include <list>
#include <unordered_set>
#include <crypto/mem.h>
#include "sec_profile.hpp"

Expand Down Expand Up @@ -223,12 +224,25 @@ static_assert(RNP_LOCATOR_MAX_SIZE > MAX_ID_LENGTH, "Locator size mismatch.");

struct rnp_identifier_iterator_st {
rnp_ffi_t ffi;
pgp_key_search_type_t type;
rnp::KeySearch::Type type;
rnp::KeyStore * store;
std::list<pgp_key_t>::iterator *keyp;
unsigned uididx;
json_object * tbl;
char buf[RNP_LOCATOR_MAX_SIZE];
size_t uididx;
std::unordered_set<std::string> tbl;
std::string item;

rnp_identifier_iterator_st(rnp_ffi_t affi, rnp::KeySearch::Type atype)
: ffi(affi), type(atype)
{
store = nullptr;
keyp = new std::list<pgp_key_t>::iterator();
uididx = 0;
}

~rnp_identifier_iterator_st()
{
delete keyp;
}
};

struct rnp_decryption_kp_param_t {
Expand Down
205 changes: 199 additions & 6 deletions src/lib/key-provider.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, [Ribose Inc](https://www.ribose.com).
* Copyright (c) 2017-2024 [Ribose Inc](https://www.ribose.com).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
Expand All @@ -24,28 +24,221 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <assert.h>
#include <string.h>
#include <string>
#include <map>
#include "key-provider.h"
#include "pgp-key.h"
#include "fingerprint.h"
#include "types.h"
#include "utils.h"
#include "str-utils.h"
#include "crypto/mem.h"
#include <rekey/rnp_key_store.h>

namespace rnp {

KeySearch::Type
KeySearch::find_type(const std::string &name)
{
static const std::map<const std::string, KeySearch::Type> types = {
{"keyid", Type::KeyID},
{"fingerprint", Type::Fingerprint},
{"grip", Type::Grip},
{"userid", Type::UserID}};
if (types.find(name) == types.end()) {
return Type::Unknown;
}
return types.at(name);
}

std::unique_ptr<KeySearch>
KeySearch::create(const pgp_key_id_t &keyid)
{
return std::unique_ptr<KeySearch>(new KeyIDSearch(keyid));
}

std::unique_ptr<KeySearch>
KeySearch::create(const pgp_fingerprint_t &fp)
{
return std::unique_ptr<KeySearch>(new KeyFingerprintSearch(fp));
}

std::unique_ptr<KeySearch>
KeySearch::create(const pgp_key_grip_t &grip)
{
return std::unique_ptr<KeySearch>(new KeyGripSearch(grip));
}

std::unique_ptr<KeySearch>
KeySearch::create(const std::string &uid)
{
return std::unique_ptr<KeySearch>(new KeyUIDSearch(uid));
}

std::unique_ptr<KeySearch>
KeySearch::create(const std::string &name, const std::string &value)
{
auto type = find_type(name);
if (type == Type::Unknown) {
return nullptr;
}
if (type == Type::UserID) {
return create(value);
}
/* All the rest values are hex-encoded */
auto binval = hex_to_bin(value);
if (binval.empty()) {
return nullptr;
}
switch (type) {
case Type::Fingerprint:
if (!pgp_fingerprint_t::size_valid(binval.size())) {
RNP_LOG("Invalid fingerprint: %s", value.c_str());
return nullptr;
}
return create(pgp_fingerprint_t(binval));
case Type::KeyID:
if (binval.size() != PGP_KEY_ID_SIZE) {
RNP_LOG("Invalid keyid: %s", value.c_str());
return nullptr;
}
pgp_key_id_t keyid;
memcpy(keyid.data(), binval.data(), keyid.size());
return create(keyid);
case Type::Grip:
if (binval.size() != PGP_KEY_GRIP_SIZE) {
RNP_LOG("Invalid grip: %s", value.c_str());
return nullptr;
}
pgp_key_grip_t grip;
memcpy(grip.data(), binval.data(), grip.size());
return create(grip);
default:
return nullptr;
}
}

bool
KeyIDSearch::matches(const pgp_key_t &key) const
{
return (key.keyid() == keyid_) || (keyid_ == pgp_key_id_t({}));
}

const std::string
KeyIDSearch::name() const
{
return "keyid";
}

std::string
KeyIDSearch::value() const
{
return bin_to_hex(keyid_.data(), keyid_.size());
}

bool
KeyIDSearch::hidden() const
{
return keyid_ == pgp_key_id_t({});
}

KeyIDSearch::KeyIDSearch(const pgp_key_id_t &keyid)
{
type_ = Type::KeyID;
keyid_ = keyid;
}

bool
KeyFingerprintSearch::matches(const pgp_key_t &key) const
{
return key.fp() == fp_;
}

const std::string
KeyFingerprintSearch::name() const
{
return "fingerprint";
}

std::string
KeyFingerprintSearch::value() const
{
return bin_to_hex(fp_.fingerprint, fp_.length);
}

KeyFingerprintSearch::KeyFingerprintSearch(const pgp_fingerprint_t &fp)
{
type_ = Type::Fingerprint;
fp_ = fp;
}

const pgp_fingerprint_t &
KeyFingerprintSearch::get_fp() const
{
return fp_;
}

bool
KeyGripSearch::matches(const pgp_key_t &key) const
{
return key.grip() == grip_;
}

const std::string
KeyGripSearch::name() const
{
return "grip";
}

std::string
KeyGripSearch::value() const
{
return bin_to_hex(grip_.data(), grip_.size());
}

KeyGripSearch::KeyGripSearch(const pgp_key_grip_t &grip)
{
type_ = Type::Grip;
grip_ = grip;
}

bool
KeyUIDSearch::matches(const pgp_key_t &key) const
{
return key.has_uid(uid_);
}

const std::string
KeyUIDSearch::name() const
{
return "userid";
}

std::string
KeyUIDSearch::value() const
{
return uid_;
}

KeyUIDSearch::KeyUIDSearch(const std::string &uid)
{
type_ = Type::UserID;
uid_ = uid;
}

pgp_key_t *
KeyProvider::request_key(const pgp_key_request_ctx_t &ctx) const
KeyProvider::request_key(const KeySearch &search, pgp_op_t op, bool secret) const
{
pgp_key_t *key = nullptr;
if (!callback) {
return key;
}
pgp_key_request_ctx_t ctx(op, secret, search);
if (!(key = callback(&ctx, userdata))) {
return nullptr;
}
// confirm that the key actually matches the search criteria
if (!key->matches(ctx.search) || (key->is_secret() != ctx.secret)) {
if (!search.matches(*key) || (key->is_secret() != secret)) {
return nullptr;
}
return key;
Expand All @@ -57,7 +250,7 @@ rnp_key_provider_key_ptr_list(const pgp_key_request_ctx_t *ctx, void *userdata)
{
std::vector<pgp_key_t *> *key_list = (std::vector<pgp_key_t *> *) userdata;
for (auto key : *key_list) {
if (key->matches(ctx->search) && (key->is_secret() == ctx->secret)) {
if (ctx->search.matches(*key) && (key->is_secret() == ctx->secret)) {
return key;
}
}
Expand Down
Loading

0 comments on commit 7165af6

Please sign in to comment.