put previously global error handling and key hashes into ptx (pcp context) to make libpcp threadsafe.

This commit is contained in:
TLINDEN
2014-05-04 17:11:03 +02:00
parent d1c87d1001
commit da9891ff81
58 changed files with 1330 additions and 958 deletions

View File

@@ -22,5 +22,5 @@ AM_CXXFLAGS = -I../../include -I../../libpcp/scrypt/crypto -I../../libpcp/scrypt
lib_LTLIBRARIES = libpcp1++.la
libpcp1___la_SOURCES = pcp++.h key.cpp vault.cpp crypto.cpp sign.cpp buffer.cpp
libpcp1___la_SOURCES = pcp++.h ptx.cpp key.cpp vault.cpp crypto.cpp sign.cpp buffer.cpp
include_HEADERS = pcp++.h

View File

@@ -35,6 +35,7 @@ namespace pcp {
class Crypto {
private:
PcpContext PTX;
bool havevault;
public:
@@ -43,8 +44,8 @@ namespace pcp {
Vault vault;
// constructors
Crypto(Key &skey, PubKey &pkey);
Crypto(Vault &v, Key &skey, PubKey &pkey);
Crypto(PcpContext C, Key &skey, PubKey &pkey);
Crypto(PcpContext C, Vault &v, Key &skey, PubKey &pkey);
// PK encryption methods
// sender pubkey is P

View File

@@ -25,29 +25,31 @@
using namespace std;
using namespace pcp;
Crypto::Crypto(Key &skey, PubKey &pkey) {
Crypto::Crypto(PcpContext C, Key &skey, PubKey &pkey) {
P = pkey;
S = skey;
PTX = C;
havevault = false;
pcphash_init();
pcphash_add(P.K, PCP_KEY_TYPE_PUBLIC);
pcphash_add(PTX.ptx, P.K, PCP_KEY_TYPE_PUBLIC);
}
Crypto::Crypto(Vault &v, Key &skey, PubKey &pkey) {
Crypto::Crypto(PcpContext C, Vault &v, Key &skey, PubKey &pkey) {
P = pkey;
S = skey;
PTX = C;
vault = v;
havevault = true;
}
bool Crypto::encrypt(FILE *in, FILE *out, bool sign) {
pcp_pubkey_t *pubhash = NULL;
HASH_ADD_STR( pubhash, id, P.K);
pcphash_add(PTX.ptx, P.K, P.K->type);
//HASH_ADD_STR( pubhash, id, P.K);
Pcpstream *pin = ps_new_file(in);
Pcpstream *pout = ps_new_file(out);
size_t clen = pcp_encrypt_stream(pin, pout, S.K, pubhash, sign);
size_t clen = pcp_encrypt_stream(PTX.ptx, pin, pout, S.K, pubhash, sign);
if(clen <= 0)
throw exception();
throw exception(PTX);
ps_close(pin);
ps_close(pout);
return true;
@@ -56,8 +58,8 @@ bool Crypto::encrypt(FILE *in, FILE *out, bool sign) {
bool Crypto::decrypt(FILE *in, FILE *out, bool verify) {
Pcpstream *pin = ps_new_file(in);
Pcpstream *pout = ps_new_file(out);
if(pcp_decrypt_stream(pin, pout, S.K, NULL, verify) <= 0)
throw exception();
if(pcp_decrypt_stream(PTX.ptx, pin, pout, S.K, NULL, verify) <= 0)
throw exception(PTX);
ps_close(pin);
ps_close(pout);
return true;

View File

@@ -30,14 +30,17 @@
#include <stdexcept>
#include <iostream>
#include "ptx++.h"
namespace pcp {
class exception : public std::runtime_error {
private:
PCPCTX *ptx;
std::string getfatals() {
std::string msg;
if(PCP_ERRSET == 1) {
msg = PCP_ERR;
if(ptx->pcp_errset == 1) {
msg = ptx->pcp_err;
}
if(errno) {
msg += std::string("\nError: ")
@@ -47,8 +50,8 @@ namespace pcp {
return msg;
}
public:
exception(const std::string & msg) : runtime_error(msg) { }
exception() : runtime_error(getfatals()) { }
exception(PcpContext P, const std::string & msg) : runtime_error(msg) { ptx = P.ptx; }
exception(PcpContext P) : runtime_error(getfatals()) { ptx = P.ptx; }
};

View File

@@ -30,6 +30,7 @@
#include "helpers++.h"
#include "buffer++.h"
#include "ptx++.h"
namespace pcp {
@@ -39,12 +40,14 @@ namespace pcp {
public:
pcp_pubkey_t *K;
PcpContext PTX;
// constructors
PubKey(PcpContext P);
PubKey();
PubKey(pcp_pubkey_t *k);
PubKey(pcp_pubkey_t *k, bool store);
PubKey(std::string &z85encoded);
PubKey(PcpContext P, pcp_pubkey_t *k);
PubKey(PcpContext P, pcp_pubkey_t *k, bool store);
PubKey(PcpContext P, std::string &z85encoded);
// destructors
~PubKey();
@@ -72,17 +75,19 @@ namespace pcp {
public:
// make access to the underlying struct easier
pcp_key_t *K;
PcpContext PTX;
// constructors
Key();
Key(bool generate);
Key(const std::string& passphrase);
Key(const std::string& passphrase,
Key(PcpContext P);
Key(PcpContext P, bool generate);
Key(PcpContext P, const std::string& passphrase);
Key(PcpContext P, const std::string& passphrase,
const std::string& owner,
const std::string& mail);
Key(pcp_key_t *k);
Key(pcp_key_t *k, bool store);
Key(std::string &z85encoded, std::string& passphrase);
Key(PcpContext P, pcp_key_t *k);
Key(PcpContext P, pcp_key_t *k, bool store);
Key(PcpContext P, std::string &z85encoded, std::string& passphrase);
// destructor
~Key();

View File

@@ -30,55 +30,67 @@ Key::Key() {
K = NULL;
}
Key::Key(bool generate) {
Key::Key(PcpContext P) {
stored = false;
K = NULL;
PTX = P;
}
Key::Key(PcpContext P, bool generate) {
stored = false;
if(generate)
K = pcpkey_new();
else
K = NULL;
PTX = P;
}
Key::Key(const string& passphrase) {
Key::Key(PcpContext P, const string& passphrase) {
stored = false;
K = pcpkey_new();
K = pcpkey_encrypt(K, (char *)passphrase.c_str());
K = pcpkey_encrypt(PTX.ptx, K, (char *)passphrase.c_str());
PTX = P;
}
Key::Key(const string& passphrase,
Key::Key(PcpContext P, const string& passphrase,
const string& owner,
const string& mail) {
stored = false;
pcp_key_t *_K = pcpkey_new();
K = pcpkey_encrypt(_K, (char *)passphrase.c_str());
K = pcpkey_encrypt(PTX.ptx, _K, (char *)passphrase.c_str());
memcpy(K->owner, owner.c_str(), owner.length()+1);
memcpy(K->mail, mail.c_str(), mail.length()+1);
// free(_K);
PTX = P;
}
Key::Key(pcp_key_t *k) {
Key::Key(PcpContext P, pcp_key_t *k) {
stored = false;
K = k;
PTX = P;
}
Key::Key(pcp_key_t *k, bool store) {
Key::Key(PcpContext P, pcp_key_t *k, bool store) {
stored = new bool(store);
K = k;
PTX = P;
}
Key::Key(string &z85encoded, string &passphrase) {
Key::Key(PcpContext P, string &z85encoded, string &passphrase) {
stored = false;
PTX = P;
if(z85encoded.length() == 0)
throw pcp::exception("Error: zero length input");
throw pcp::exception(PTX, "Error: zero length input");
pcp_key_t *key = pcp_import_secret((unsigned char *)z85encoded.c_str(), z85encoded.length(), (char *)passphrase.c_str());
pcp_key_t *key = pcp_import_secret(PTX.ptx, (unsigned char *)z85encoded.c_str(), z85encoded.length(), (char *)passphrase.c_str());
if(key == NULL)
throw pcp::exception();
throw pcp::exception(PTX);
if(pcp_sanitycheck_key(key) != 0) {
if(pcp_sanitycheck_key(PTX.ptx, key) != 0) {
free(key);
throw pcp::exception();
throw pcp::exception(PTX);
}
K = key;
@@ -99,12 +111,12 @@ string Key::export_secret(const string &passphrase) {
Buffer *exported_sk;
if(passphrase.length() == 0)
throw pcp::exception("Error: empty passphrase");
throw pcp::exception(PTX, "Error: empty passphrase");
exported_sk = pcp_export_secret(K, (char *)passphrase.c_str());
exported_sk = pcp_export_secret(PTX.ptx, K, (char *)passphrase.c_str());
if(exported_sk == NULL)
throw pcp::exception();
throw pcp::exception(PTX);
size_t zlen;
char *z85 = pcp_z85_encode(buffer_get(exported_sk), buffer_size(exported_sk), &zlen);
@@ -120,7 +132,7 @@ string Key::export_public() {
exported_pk = pcp_export_rfc_pub(K);
if(exported_pk == NULL)
throw pcp::exception();
throw pcp::exception(PTX);
size_t zlen;
char *z85 = pcp_z85_encode(buffer_get(exported_pk), buffer_size(exported_pk), &zlen);
@@ -140,19 +152,19 @@ bool pcp::operator!(Key& k) {
void Key::encrypt(const string& passphrase) {
K = pcpkey_encrypt(K, (char *)passphrase.c_str());
if(PCP_ERRSET == 1)
throw exception();
K = pcpkey_encrypt(PTX.ptx, K, (char *)passphrase.c_str());
if(K == NULL)
throw exception(PTX);
}
void Key::decrypt(const string& passphrase) {
K = pcpkey_decrypt(K, (char *)passphrase.c_str());
if(PCP_ERRSET == 1)
throw exception();
K = pcpkey_decrypt(PTX.ptx, K, (char *)passphrase.c_str());
if(K == NULL)
throw exception(PTX);
}
PubKey Key::get_public() {
return PubKey(pcpkey_pub_from_secret(K));
return PubKey(PTX, pcpkey_pub_from_secret(K));
}
string Key::get_id() {
@@ -197,44 +209,52 @@ bool Key::is_encrypted() {
PubKey::PubKey() {
stored = false;
K = NULL;
}
PubKey::PubKey(pcp_pubkey_t *k) {
PubKey::PubKey(PcpContext P) {
stored = false;
K = k;
K = NULL;
PTX = P;
}
PubKey::PubKey(pcp_pubkey_t *k, bool store) {
PubKey::PubKey(PcpContext P, pcp_pubkey_t *k) {
stored = false;
K = k;
PTX = P;
}
PubKey::PubKey(PcpContext P, pcp_pubkey_t *k, bool store) {
stored = store;
K = k;
PTX = P;
}
PubKey::PubKey(string &z85encoded) {
PubKey::PubKey(PcpContext P, string &z85encoded) {
stored = false;
PTX = P;
if(z85encoded.length() == 0)
throw pcp::exception("Error: zero length input");
throw pcp::exception(PTX, "Error: zero length input");
Buf blob("pub", 256);
blob.add(z85encoded.c_str(), z85encoded.length());
pcp_ks_bundle_t *KS = pcp_import_pub(buffer_get(blob.get_buffer()), buffer_size(blob.get_buffer()));
pcp_ks_bundle_t *KS = pcp_import_pub(PTX.ptx, buffer_get(blob.get_buffer()), buffer_size(blob.get_buffer()));
if(KS == NULL) {
throw pcp::exception();
throw pcp::exception(PTX);
}
pcp_pubkey_t *pub = KS->p;
if(pcp_sanitycheck_pub(pub) != 0) {
if(pcp_sanitycheck_pub(PTX.ptx, pub) != 0) {
free(KS->p);
free(KS->s);
free(KS);
throw pcp::exception();
throw pcp::exception(PTX);
}
K = pub;

View File

@@ -32,6 +32,7 @@
#include <iostream>
#include "key++.h"
#include "ptx++.h"
#include "vault++.h"
#include "crypto++.h"
#include "sign++.h"

48
bindings/cpp/ptx++.h Normal file
View File

@@ -0,0 +1,48 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T.Linden.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tlinden AT cpan DOT org>.
*/
#ifndef _HAVE_PCPPP_PTX_H
#define _HAVE_PCPPP_PTX_H
#include <pcp.h>
#include <vector>
#include <string>
#include <iostream>
#include "helpers++.h"
namespace pcp {
class PcpContext {
public:
PCPCTX *ptx;
// constructors
PcpContext();
// destructors
~PcpContext();
};
};
#endif // _HAVE_PCPPP_PTX_H

34
bindings/cpp/ptx.cpp Normal file
View File

@@ -0,0 +1,34 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T.Linden.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tlinden AT cpan DOT org>.
*/
#include "pcp++.h"
using namespace std;
using namespace pcp;
PcpContext::PcpContext() {
ptx = ptx_new();
}
PcpContext::~PcpContext() {
ptx_clean(ptx);
}

View File

@@ -45,12 +45,13 @@ namespace pcp {
Vault vault;
PubKey Signedby;
Buf sig;
PcpContext PTX;
// constructors
Signature(Key &skey); // sign only
Signature(PubKey &pkey); // verify only
Signature(Key &skey, PubKey &pkey); // both/bulk
Signature(Vault &v);
Signature(PcpContext P, Key &skey); // sign only
Signature(PcpContext P,PubKey &pkey); // verify only
Signature(PcpContext P,Key &skey, PubKey &pkey); // both/bulk
Signature(PcpContext P,Vault &v);
// destructor
~Signature();

View File

@@ -24,25 +24,29 @@
using namespace std;
using namespace pcp;
Signature::Signature(Key &skey) {
Signature::Signature(PcpContext P, Key &skey) {
S = skey;
PTX = P;
havevault = false;
}
Signature::Signature(PubKey &pkey) {
Signature::Signature(PcpContext C,PubKey &pkey) {
P = pkey;
PTX = C;
havevault = false;
}
Signature::Signature(Key &skey, PubKey &pkey) {
Signature::Signature(PcpContext C,Key &skey, PubKey &pkey) {
P = pkey;
S = skey;
PTX = C;
havevault = false;
}
Signature::Signature(Vault &v) {
Signature::Signature(PcpContext P,Vault &v) {
vault = v;
havevault = true;
PTX = P;
S = vault.get_primary();
}
@@ -51,10 +55,10 @@ Signature::~Signature() {
bool Signature::sign(std::vector<unsigned char> message) {
if(! S)
throw exception("Error: cannot sign without a secret key, use another constructor.");
throw exception(PTX, "Error: cannot sign without a secret key, use another constructor.");
if(S.is_encrypted())
throw exception("Error: cannot sign with an encrypted secret key, decrypt it before using.");
throw exception(PTX, "Error: cannot sign with an encrypted secret key, decrypt it before using.");
char n[] = "signvec";
Buffer *m = buffer_new(32, n);
@@ -68,17 +72,17 @@ bool Signature::sign(std::vector<unsigned char> message) {
buffer_free(m);
if(!ok)
throw exception();
throw exception(PTX);
return true;
}
bool Signature::sign(unsigned char *message, size_t mlen) {
if(! S)
throw exception("Error: cannot sign without a secret key, use another constructor.");
throw exception(PTX, "Error: cannot sign without a secret key, use another constructor.");
if(S.is_encrypted())
throw exception("Error: cannot sign with an encrypted secret key, decrypt it before using.");
throw exception(PTX, "Error: cannot sign with an encrypted secret key, decrypt it before using.");
char n[] = "signchar";
Buffer *m = buffer_new(32, n);
@@ -90,7 +94,7 @@ bool Signature::sign(unsigned char *message, size_t mlen) {
buffer_free(m);
if(! ok)
throw exception();
throw exception(PTX);
return true;
}
@@ -98,7 +102,7 @@ bool Signature::sign(unsigned char *message, size_t mlen) {
bool Signature::sign(Pcpstream *message) {
Pcpstream *out = ps_new_outbuffer();
size_t sigsize = pcp_ed_sign_buffered(message, out, S.K, 0);
size_t sigsize = pcp_ed_sign_buffered(PTX.ptx, message, out, S.K, 0);
if(sigsize > 0) {
Buffer *o = ps_buffer(out);
@@ -115,7 +119,7 @@ bool Signature::sign(Pcpstream *message) {
bool Signature::verify(vector<unsigned char> message) {
if(!P) {
throw exception("No public key specified, unable to verify.");
throw exception(PTX, "No public key specified, unable to verify.");
}
Buf _sig = Buf();
@@ -128,7 +132,7 @@ bool Signature::verify(vector<unsigned char> message) {
bool Signature::verify(unsigned char *signature, size_t mlen) {
if(!P) {
throw exception("No public key specified, unable to verify.");
throw exception(PTX, "No public key specified, unable to verify.");
}
Buf _sig = Buf();
@@ -141,15 +145,15 @@ bool Signature::verify(unsigned char *signature, size_t mlen) {
bool Signature::verify(Buf _sig) {
Pcpstream *p = ps_new_inbuffer(_sig.get_buffer());
pcp_pubkey_t *pub = pcp_ed_verify_buffered(p, P.K);
pcp_pubkey_t *pub = pcp_ed_verify_buffered(PTX.ptx, p, P.K);
ps_close(p);
if(pub != NULL) {
Signedby = PubKey(pub);
Signedby = PubKey(PTX, pub);
return true;
}
else {
throw exception();
throw exception(PTX);
}
}

View File

@@ -46,11 +46,13 @@ namespace pcp {
class Vault {
private:
vault_t *V;
PcpContext PTX;
public:
// constructors
Vault();
Vault(std::string filename);
Vault(PcpContext P);
Vault(PcpContext P, std::string filename);
// destructor
~Vault();

View File

@@ -28,24 +28,28 @@ Vault::Vault() {
V = NULL;
}
Vault::Vault(string filename) {
pcphash_init();
V = pcpvault_init((char *)filename.c_str());
Vault::Vault(PcpContext P) {
V = NULL;
PTX = P;
}
Vault::Vault(PcpContext P, string filename) {
PTX = P;
V = pcpvault_init(PTX.ptx, (char *)filename.c_str());
if (V == NULL)
throw pcp::exception();
throw pcp::exception(PTX);
}
Vault::~Vault() {
pcpvault_close(V);
pcphash_clean();
pcpvault_close(PTX.ptx, V);
}
std::map<std::string, Key> Vault::keys() {
std::map<std::string, Key> kmap;
pcp_key_t *k = NULL;
pcphash_iterate(k) {
kmap.insert ( pair<string,Key>(string(k->id), Key(k, true)) );
pcphash_iterate(PTX.ptx, k) {
kmap.insert ( pair<string,Key>(string(k->id), Key(PTX, k, true)) );
}
return kmap;
@@ -55,39 +59,39 @@ std::map<std::string, PubKey> Vault::pubkeys() {
std::map<std::string, PubKey> kmap;
pcp_pubkey_t *k = NULL;
pcphash_iteratepub(k) {
kmap.insert ( pair<string,PubKey>(string(k->id), PubKey(k, true)) );
pcphash_iteratepub(PTX.ptx, k) {
kmap.insert ( pair<string,PubKey>(string(k->id), PubKey(PTX, k, true)) );
}
return kmap;
}
int Vault::key_count() {
return pcphash_count();
return pcphash_count(PTX.ptx);
}
int Vault::pubkey_count() {
return pcphash_countpub();
return pcphash_countpub(PTX.ptx);
}
void Vault::key_add(Key &key) {
if(V->isnew == 1 || HASH_COUNT(pcpkey_hash) == 0) {
if(V->isnew == 1 || pcphash_count(PTX.ptx) == 0) {
key.K->type = PCP_KEY_TYPE_MAINSECRET;
}
if(pcpvault_addkey(V, (void *)key.K, key.K->type) != 0)
throw pcp::exception();
if(pcpvault_addkey(PTX.ptx, V, (void *)key.K, key.K->type) != 0)
throw pcp::exception(PTX);
key.is_stored(true);
}
void Vault::pubkey_add(PubKey &key) {
if(pcpvault_addkey(V, (void *)key.K, key.K->type) != 0)
throw pcp::exception();
if(pcpvault_addkey(PTX.ptx, V, (void *)key.K, key.K->type) != 0)
throw pcp::exception(PTX);
key.is_stored(true);
}
bool Vault::key_exists(string &id) {
pcp_key_t *s = pcphash_keyexists((char *)id.c_str());
pcp_key_t *s = pcphash_keyexists(PTX.ptx, (char *)id.c_str());
if(s == NULL)
return false;
else
@@ -95,7 +99,7 @@ bool Vault::key_exists(string &id) {
}
bool Vault::pubkey_exists(string &id) {
pcp_pubkey_t *p = pcphash_pubkeyexists((char *)id.c_str());
pcp_pubkey_t *p = pcphash_pubkeyexists(PTX.ptx, (char *)id.c_str());
if(p == NULL)
return false;
else
@@ -103,63 +107,63 @@ bool Vault::pubkey_exists(string &id) {
}
void Vault::key_delete(std::string &id) {
pcp_pubkey_t *p = pcphash_pubkeyexists((char *)id.c_str());
pcp_pubkey_t *p = pcphash_pubkeyexists(PTX.ptx, (char *)id.c_str());
if(p != NULL) {
// delete public
HASH_DEL(pcppubkey_hash, p);
pcphash_del(PTX.ptx, p, p->type);
free(p);
V->unsafed = 1;
}
else {
pcp_key_t *s = pcphash_keyexists((char *)id.c_str());
pcp_key_t *s = pcphash_keyexists(PTX.ptx, (char *)id.c_str());
if(s != NULL) {
// delete secret
HASH_DEL(pcpkey_hash, s);
pcphash_del(PTX.ptx, s, s->type);
free(s);
V->unsafed = 1;
}
else {
throw exception("Key not found!\n");
throw exception(PTX, "Key not found!\n");
}
}
}
Key Vault::get_primary() {
pcp_key_t *k = NULL;
pcphash_iterate(k) {
pcphash_iterate(PTX.ptx, k) {
if(k->type == PCP_KEY_TYPE_MAINSECRET) {
return Key(k);
return Key(PTX, k);
}
}
if(Vault::key_count() == 1) {
pcphash_iterate(k) {
return Key(k);
pcphash_iterate(PTX.ptx, k) {
return Key(PTX, k);
}
}
// too bad
throw exception("No primary key found in vault.");
throw exception(PTX, "No primary key found in vault.");
}
Key Vault::get_secret(std::string &id) {
pcp_key_t *k = NULL;
pcphash_iterate(k) {
pcphash_iterate(PTX.ptx, k) {
if(memcmp(k->id, id.c_str(), 16) == 0) {
return Key(k);
return Key(PTX, k);
}
}
throw exception("Secret key doesn't exist in vault.");
throw exception(PTX, "Secret key doesn't exist in vault.");
}
PubKey Vault::get_public(std::string &id) {
pcp_pubkey_t *k = NULL;
pcphash_iteratepub(k) {
pcphash_iteratepub(PTX.ptx, k) {
if(memcmp(k->id, id.c_str(), 16) == 0) {
return PubKey(k);
return PubKey(PTX, k);
}
}
throw exception("Public key doesn't exist in vault.");
throw exception(PTX, "Public key doesn't exist in vault.");
}