Sleds/libeye/eyeinterface.cpp

1183 lines
35 KiB
C++

// Copyright (c) 2013-2015 IONU Security, Inc. All rights reserved
// Copyright (c) 2016 Sequence Logic, Inc. All rights reserved
//
// C interface to the EyeContainer
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <iostream>
#include <fstream>
#include "eyeencrypteddb.h"
#include "eyeinterface.h"
#include "eyejson.h"
#include "eyelock.h"
#include "eyelog.h"
#include "eyering.h"
#include "eyeutils.h"
using namespace sequencelogic;
pthread_mutex_t ionu_policy_mutex = PTHREAD_MUTEX_INITIALIZER;
namespace sequencelogic {
EyeJSONObject* GlobalPolicy = NULL;
long GlobalPolicyTGIExpiration = 86400000; // Default to one day
static const char* const PRIMARY_ID = "_id";
static const char* const POLICY = "policies";
static const char* const POLICYNAME = "policyName";
static const char* const POLICYVALUE = "policyValue";
static const char* const PUBLICKEY = "publicKey";
static const char* const KEY = "key";
}
bool ionu_configfilelog (const char* app, const char* device, EYE_LOG_LEVEL level, const char* logfile)
{
if (!app || !device || !sequencelogic::IsValidFilename (logfile))
return false;
EyeLog::LOG_LEVEL lvl = EyeLog::IONU_TRACE;
switch (level) {
case IONU_FATAL :
lvl = EyeLog::IONU_FATAL;
break;
case IONU_ERROR :
lvl = EyeLog::IONU_ERROR;
break;
case IONU_WARN :
lvl = EyeLog::IONU_WARN;
break;
case IONU_INFO :
lvl = EyeLog::IONU_INFO;
break;
case IONU_DEBUG :
lvl = EyeLog::IONU_DEBUG;
break;
case IONU_VERBOSE :
lvl = EyeLog::IONU_TRACE;
break;
}
return IONUCONFIGFILELOG (app, device, lvl, logfile);
}
bool ionu_configlog (const char* app, const char* device, EYE_LOG_LEVEL level, EYE_LOG_SINK sink)
{
if (!app || !device)
return false;
EyeLog::LOG_LEVEL lvl = EyeLog::IONU_TRACE;
switch (level) {
case IONU_FATAL :
lvl = EyeLog::IONU_FATAL;
break;
case IONU_ERROR :
lvl = EyeLog::IONU_ERROR;
break;
case IONU_WARN :
lvl = EyeLog::IONU_WARN;
break;
case IONU_INFO :
lvl = EyeLog::IONU_INFO;
break;
case IONU_DEBUG :
lvl = EyeLog::IONU_DEBUG;
break;
case IONU_VERBOSE :
lvl = EyeLog::IONU_TRACE;
break;
}
EyeLog::LOG_SINK snk = EyeLog::IONU_CONSOLE;
if (sink == IONU_SYSLOG)
snk = EyeLog::IONU_SYSLOG;
return IONUCONFIGLOG (app, device, lvl, snk);
}
void ionu_log (EYE_LOG_LEVEL level, const char* msg)
{
if (!msg)
return;
switch (level) {
case IONU_FATAL :
IONUFATAL ("%s", msg);
break;
case IONU_ERROR :
IONUERROR ("%s", msg);
break;
case IONU_WARN :
IONUWARN ("%s", msg);
break;
case IONU_INFO :
IONUINFO ("%s", msg);
break;
case IONU_DEBUG :
IONUDEBUG ("%s", msg);
break;
case IONU_VERBOSE :
default :
IONUTRACE ("%s", msg);
break;
}
}
bool ionu_closelog()
{
return IONUCLOSELOG();
}
bool ionu_policy_install (const char* jsonPolicy)
{
// Check for garbage input
if (sequencelogic::StrLen (jsonPolicy, 4096) == 0)
return false;
#ifndef WIN32
pthread_mutex_lock (&ionu_policy_mutex);
#endif
if (sequencelogic::GlobalPolicy)
delete sequencelogic::GlobalPolicy;
sequencelogic::GlobalPolicy = new EyeJSONObject (jsonPolicy);
#ifndef WIN32
pthread_mutex_unlock (&ionu_policy_mutex);
#endif
return true;
}
bool ionu_policy_uninstall ()
{
#ifndef WIN32
pthread_mutex_lock (&ionu_policy_mutex);
#endif
if (sequencelogic::GlobalPolicy)
delete sequencelogic::GlobalPolicy;
sequencelogic::GlobalPolicy = NULL;
#ifndef WIN32
pthread_mutex_unlock (&ionu_policy_mutex);
#endif
return true;
}
char* ionu_policy_check (const char* policyName)
{
// Check for garbage input
if (sequencelogic::StrLen (policyName, 32) == 0)
return NULL;
char* json = NULL;
if (sequencelogic::GlobalPolicy) {
#ifndef WIN32
pthread_mutex_lock (&ionu_policy_mutex);
#endif
EyeJSONObject* policies = dynamic_cast<EyeJSONObject*>(GlobalPolicy->GetMember (POLICY));
if (policies) {
for (size_t i = 0; i < policies->GetNumMembers(); ++i) {
EyeJSONObject* policy = dynamic_cast<EyeJSONObject*>(policies->GetMember (i));
if (policy && policy->GetType() == JSON_OBJECT) {
EyeJSONNode* item = policy->GetMember (POLICYNAME);
if (item && strcmp (dynamic_cast<EyeJSONScalar*>(item)->GetValue(), policyName) == 0) {
std::string cppjson;
policy->GetJSONString (cppjson);
if (cppjson.length() > 0) {
json = (char*)malloc (cppjson.length() + 1);
sequencelogic::StrCpy (json, cppjson.c_str()); // Protects if malloc failed
}
}
}
}
}
#ifndef WIN32
pthread_mutex_unlock (&ionu_policy_mutex);
#endif
}
return json;
}
bool ionu_base64_encode (const unsigned char *input, size_t len, char *output)
{
return sequencelogic::Base64Encode (input, len, output);
}
size_t ionu_base64_decode (const char *input, unsigned char *output)
{
return sequencelogic::Base64Decode (input, output);
}
char* ionu_digest_msg (const char* digest, const unsigned char* msg, size_t len)
{
char* sig = NULL;
if (digest && msg) {
std::string cppsig = sequencelogic::DigestMessage (digest, msg, len);
if (cppsig.size() > 0) {
sig = (char*)malloc (cppsig.size() + 1);
sequencelogic::StrCpy (sig, cppsig.c_str()); // Protects if malloc failed
}
}
return sig;
}
char* ionu_digest_file (const char* digest, const char* filename)
{
char* sig = NULL;
if (digest && filename) {
std::string cppsig = sequencelogic::DigestFile (digest, filename);
if (cppsig.size() > 0) {
sig = (char*)malloc (cppsig.size() + 1);
sequencelogic::StrCpy (sig, cppsig.c_str()); // Protects if malloc failed
}
}
return sig;
}
char* ionu_hmac_msg (const unsigned char* key, size_t klen, const unsigned char* msg, size_t mlen)
{
char* sig = NULL;
if (key && msg) {
std::string cppsig = sequencelogic::HMACMessage (key, klen, msg, mlen);
if (cppsig.size() > 0) {
sig = (char*)malloc (cppsig.size() + 1);
sequencelogic::StrCpy (sig, cppsig.c_str()); // Protects if malloc failed
}
}
return sig;
}
size_t ionu_symmetric_encrypt_buffer_pass (const char* passphrase, const unsigned char* in, size_t inlen, unsigned char* out)
{
unsigned char key[EVP_MAX_KEY_LENGTH];
unsigned char iv[16];
memset (key, 0, EVP_MAX_KEY_LENGTH);
memset (iv, 0, 16);
size_t outlen = 0;
//const EVP_CIPHER *cipher = _ionu_sec_get_cipher(cipherName);
EVP_BytesToKey (EVP_aes_128_cbc(), EVP_md5(), NULL, (unsigned char*)passphrase, (int)strlen(passphrase), 1, key, iv);
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init (&ctx);
if (!EVP_EncryptInit (&ctx, EVP_aes_128_cbc(), key, iv)) {
EVP_CIPHER_CTX_cleanup (&ctx);
return 0;
}
int bytes, ebytes;
if (!EVP_EncryptUpdate (&ctx, out, &bytes, in, (int)inlen))
{
EVP_CIPHER_CTX_cleanup (&ctx);
return 0;
}
if (!EVP_EncryptFinal (&ctx, out + bytes, &ebytes))
{
EVP_CIPHER_CTX_cleanup (&ctx);
return 0;
}
EVP_CIPHER_CTX_cleanup (&ctx);
outlen = bytes + ebytes;
return outlen;
}
size_t ionu_symmetric_decrypt_buffer_pass (const char* passphrase, const unsigned char* in, size_t inlen, unsigned char* out)
{
unsigned char key[EVP_MAX_KEY_LENGTH];
unsigned char iv[16];
memset (key, 0, EVP_MAX_KEY_LENGTH);
memset (iv, 0, 16);
size_t outlen = 0;
//const EVP_CIPHER *cipher = _ionu_sec_get_cipher(cipherName);
EVP_BytesToKey (EVP_aes_128_cbc(), EVP_md5(), NULL, (unsigned char*)passphrase, (int)strlen(passphrase), 1, key, iv);
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init (&ctx);
if (!EVP_DecryptInit (&ctx, EVP_aes_128_cbc(), key, iv)) {
EVP_CIPHER_CTX_cleanup (&ctx);
return 0;
}
int bytes, ebytes;
if (!EVP_DecryptUpdate (&ctx, out, &bytes, in, (int)inlen))
{
EVP_CIPHER_CTX_cleanup (&ctx);
return 0;
}
if (!EVP_DecryptFinal (&ctx, out + bytes, &ebytes))
{
EVP_CIPHER_CTX_cleanup (&ctx);
return 0;
}
EVP_CIPHER_CTX_cleanup (&ctx);
outlen = bytes + ebytes;
return outlen;
}
size_t ionu_symmetric_encrypt_buffer (const unsigned char* aes, const unsigned char* in, size_t inlen,
unsigned char* out, const unsigned char* iv)
{
size_t outlen = 0;
if (aes && in && out && iv) {
Key key("temp", "orary", SL_AES_KEY_LEN, aes, Key::AES);
unsigned char* cpp = key.SymmetricEncryptBuffer (in, inlen, &outlen, iv);
if (cpp) {
sequencelogic::MemCpy (out, cpp, outlen);
delete[] cpp;
}
}
return outlen;
}
size_t ionu_symmetric_decrypt_buffer (const unsigned char* aes, const unsigned char* in, size_t inlen,
unsigned char* out, const unsigned char* iv)
{
size_t outlen = 0;
if (aes && in && out && iv) {
Key key ("temp", "orary", SL_AES_KEY_LEN, aes, Key::AES);
unsigned char* cpp = key.SymmetricDecryptBuffer (in, inlen, &outlen, iv);
if (cpp) {
sequencelogic::MemCpy (out, cpp, outlen);
delete[] cpp;
}
}
return outlen;
}
size_t ionu_private_key_decrypt (const char* pem, const unsigned char* in, size_t inlen, unsigned char* out)
{
size_t outlen = 0;
if (pem && in && out) {
Key key ("temp", "orary", pem, Key::RSA);
unsigned char* cpp = key.PrivateKeyDecrypt (in, inlen, &outlen);
if (cpp) {
sequencelogic::MemCpy (out, cpp, outlen);
delete[] cpp;
}
}
return outlen;
}
size_t ionu_private_key_encrypt (const char* pem, const unsigned char* in, size_t inlen, unsigned char* out)
{
size_t outlen = 0;
if (pem && in && out) {
Key key ("temp", "orary", pem, Key::RSA);
unsigned char* cpp = key.RSAPrivateKeyEncrypt (in, inlen, &outlen);
if (cpp) {
sequencelogic::MemCpy (out, cpp, outlen);
delete[] cpp;
}
}
return outlen;
}
size_t ionu_public_key_decrypt (const char* pem, const unsigned char* in, size_t inlen, unsigned char* out)
{
size_t outlen = 0;
if (pem && in && out) {
Key key ("temp", "orary", pem, Key::RSA_PUBLIC);
unsigned char* cpp = key.RSAPublicKeyDecrypt (in, inlen, &outlen);
if (cpp) {
sequencelogic::MemCpy (out, cpp, outlen);
delete[] cpp;
}
}
return outlen;
}
size_t ionu_public_key_encrypt (const char* pem, const unsigned char* in, size_t inlen, unsigned char* out)
{
size_t outlen = 0;
if (pem && in && out) {
Key key ("temp", "orary", pem, Key::RSA_PUBLIC);
unsigned char* cpp = key.PublicKeyEncrypt (in, inlen, &outlen);
if (cpp) {
sequencelogic::MemCpy (out, cpp, outlen);
delete[] cpp;
}
}
return outlen;
}
EYE_FILE_LOCK_STATUS ionu_eyefile_lock (const char* eyefile, const char* id, EYE_FILE_LOCK_TYPE ltype)
{
if (sequencelogic::IsValidFilename (eyefile) && id)
return (EYE_FILE_LOCK_STATUS)sequencelogic::LockFile(eyefile, id, (sequencelogic::IONU_FILE_LOCK_TYPE)ltype);
else
return EYE_FILE_LOCK_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
// Key ring functions
////////////////////////////////////////////////////////////////////////////////
bool ionu_eyering_create (const char* keyfile, const char* ring,
const char* desc, const unsigned char* rkey)
{
bool rc = false;
if (keyfile && ring && rkey) {
Keyring* r = new Keyring (ring, desc);
if (r) {
rc = r->Lock (rkey);
if (rc)
rc = r->SaveAs (keyfile);
delete r;
}
}
return rc;
}
bool ionu_eyering_add_rsakey (const char* keyfile, const char* keyname,
const char* desc, const char* pem, const unsigned char* rkey)
{
bool rc = false;
if (keyfile && keyname && pem && rkey) {
int len = static_cast<int>(strlen (pem) + 1); // Include termination byte
Keyring* ring = new Keyring (keyfile);
if (ring) {
rc = ring->Unlock (rkey);
if (rc) {
Key* k = NULL;
if (strstr (pem, "PUBLIC"))
k = new Key (keyname, desc, len, (unsigned char*)pem, Key::RSA_PUBLIC);
else
k = new Key (keyname, desc, len, (unsigned char*)pem, Key::RSA);
if (k && ring->AddKey (k)) {
rc = ring->Lock (rkey);
if (rc)
rc = ring->Save();
}
}
delete ring;
}
}
return rc;
}
bool ionu_eyering_get_key (const char* keyfile, const char* keyname, unsigned char* key, const unsigned char* rkey)
{
bool rc = false;
if (keyfile && keyname && key && rkey) {
Keyring* ring = new Keyring (keyfile);
if (ring) {
rc = ring->Unlock (rkey);
if (rc) {
const Key* k = ring->GetKey (keyname);
if (k) {
memcpy (key, k->GetKey(), k->GetLength());
rc = true;
}
else {
rc = false;
}
}
delete ring;
}
}
return rc;
}
int ionu_eyering_get_key_len (const char* keyfile, const char* keyname, const unsigned char* rkey)
{
int rc = 0;
if (keyfile && keyname && rkey) {
Keyring* ring = new Keyring (keyfile);
if (ring) {
rc = ring->Unlock (rkey);
if (rc) {
const Key* k = ring->GetKey (keyname);
if (k)
rc = static_cast<int>(k->GetLength());
}
delete ring;
}
}
return rc;
}
char* ionu_eyering_get_strkey (const char* keyfile, const char* keyname, const unsigned char* rkey)
{
char* str = NULL;
if (keyfile && keyname && rkey) {
Keyring* ring = new Keyring (keyfile);
if (ring) {
if (ring->Unlock (rkey)) {
const Key* k = ring->GetKey (keyname);
if (k) {
std::string cppk = k->GetStringKey();
if (cppk.size() > 0) {
str = (char*)malloc (k->GetLength() + 1);
sequencelogic::MemCpy (str, cppk.data(), k->GetLength() ); // Protects if malloc failed
if (str) str[k->GetLength()] = '\0'; // Terminate just in case
}
}
}
delete ring;
}
}
return str;
}
bool ionu_eyering_remove_key (const char* keyfile, const char* keyname, const unsigned char* rkey)
{
bool rc = false;
if (keyfile && keyname && rkey) {
Keyring* ring = new Keyring (keyfile);
if (ring) {
rc = ring->Unlock (rkey);
if (rc) {
rc = ring->RemoveKey (keyname);
if (rc)
rc = ring->Lock (rkey);
if (rc)
rc = ring->Save();
}
delete ring;
}
}
return rc;
}
char* ionu_eyering_get_pubkey (const char* keyfile, const char* keyname, const unsigned char* rkey)
{
bool rc = false;
char* pk = NULL;
if (keyfile && keyname && rkey) {
Keyring* ring = new Keyring (keyfile);
if (ring) {
rc = ring->Unlock (rkey);
if (rc) {
pk = ring->GetPubKey (keyname);
if (pk) {
char* keyval = (char*)malloc (strlen (pk) + 1);
sequencelogic::StrCpy (keyval, pk); // Protects if malloc failed
delete[] pk;
pk = keyval;
}
}
delete ring;
}
}
return pk;
}
bool ionu_eyering_gen_rsa_challenge (const char* keyfile, const char* keyname, const char* desc,
const char* challenges, const unsigned char* rkey)
{
bool rc = false;
if (keyfile && keyname && challenges && rkey) {
Keyring* ring = new Keyring (keyfile);
if (ring) {
rc = ring->Unlock (rkey);
if (rc) {
rc = ring->GenerateRSAKey (keyname, desc, challenges);
if (rc)
ring->Lock (rkey);
if (rc)
rc = ring->Save();
}
delete ring;
}
}
return rc;
}
bool ionu_eyering_gen_rsa_secret_challenge (const char* keyfile, const char* keyname, const char* desc,
const char* challenges, const char* secret, const char* salt,
const unsigned char* rkey)
{
bool rc = false;
if (keyfile && keyname && rkey) {
Keyring* ring = new Keyring (keyfile);
if (ring) {
rc = ring->Unlock (rkey);
if (rc) {
std::string name (keyname);
std::string dsc (desc ? desc : "");
std::string schal (challenges ? challenges : "");
std::string ssret (secret ? secret : "");
std::string ssalt (salt ? salt : "");
rc = ring->GenerateRSAKey (name, dsc, schal, ssret, ssalt);
if (rc)
ring->Lock (rkey);
if (rc)
rc = ring->Save();
}
delete ring;
}
}
return rc;
}
char* ionu_eyering_gen_rsa_secret_salt (const char* keyfile, const char* keyname, const char* desc,
const char* challenges, const char* secret, const unsigned char* rkey)
{
char* secretsalt = NULL;
std::string salt;
bool rc = false;
if (keyfile && keyname && rkey && challenges && secret) {
Keyring* ring = new Keyring (keyfile);
if (ring) {
rc = ring->Unlock (rkey);
if (rc) {
std::string name (keyname);
std::string dsc (desc ? desc : "");
std::string schal (challenges);
std::string ssret (secret);
rc = ring->GenerateRSAKey (name, dsc, schal, ssret, salt);
if (rc)
ring->Lock (rkey);
if (rc)
rc = ring->Save();
}
delete ring;
}
}
if (rc && salt.size() == 44) {
secretsalt = (char*)malloc (salt.size() + 1);
sequencelogic::StrCpy (secretsalt, salt.c_str()); // Protects if malloc failed
}
return secretsalt;
}
bool ionu_eyering_gen_rsa (const char* keyfile, const char* keyname, const char* desc, const unsigned char* rkey)
{
bool rc = false;
if (keyfile && keyname && rkey) {
Keyring* ring = new Keyring (keyfile);
if (ring) {
rc = ring->Unlock (rkey);
if (rc) {
rc = ring->GenerateRSAKey (keyname, desc);
if (rc)
ring->Lock (rkey);
if (rc)
rc = ring->Save();
}
delete ring;
}
}
return rc;
}
bool ionu_eyering_gen_rsa_pair (char* private_pem, char* public_pem)
{
bool rc = false;
Keyring* ring = new Keyring ("temp", "orary");
if (ring) {
rc = ring->GenerateRSAKey ("rsa", "pair");
if (rc) {
char* pk = (char*)ring->GetKey("rsa")->GetKey();
sequencelogic::StrCpy (private_pem, pk); // Protects against pk==NULL
pk = ring->GetPubKey("rsa");
sequencelogic::StrCpy (public_pem, pk); // Protects against pk==NULL
delete[] pk;
}
delete ring;
}
return rc;
}
bool ionu_eyering_gen_rsa_challenge_pair (const char* challenges, char* private_pem, char* public_pem)
{
bool rc = false;
Keyring* ring = new Keyring ("temp", "orary");
if (ring) {
rc = ring->GenerateRSAKey ("rsa", "pair", challenges);
if (rc) {
char* pk = (char*)ring->GetKey("rsa")->GetKey();
sequencelogic::StrCpy (private_pem, pk); // Protects against pk==NULL
pk = ring->GetPubKey("rsa");
sequencelogic::StrCpy (public_pem, pk); // Protects against pk==NULL
delete[] pk;
}
delete ring;
}
return rc;
}
bool ionu_eyering_gen_ec_challenge_pair (const char* challenges, char* private_pem, char* public_pem)
{
bool rc = false;
if (challenges && private_pem && public_pem) {
Keyring* ring = new Keyring ("temp", "orary");
if (ring) {
rc = ring->GenerateECKey ("rsa", "pair", challenges);
if (rc) {
char* pk = (char*)ring->GetKey("rsa")->GetKey();
sequencelogic::StrCpy (private_pem, pk); // Protects against pk==NULL
pk = ring->GetPubKey("rsa");
sequencelogic::StrCpy (public_pem, pk); // Protects against pk==NULL
delete[] pk;
}
delete ring;
}
}
return rc;
}
bool ionu_eyering_gen_ec_challenge (const char* keyfile, const char* keyname, const char* desc,
const char* challenges, const unsigned char* rkey)
{
bool rc = false;
if (keyfile && keyname && challenges && rkey) {
Keyring* ring = new Keyring (keyfile);
if (ring) {
rc = ring->Unlock (rkey);
if (rc) {
rc = ring->GenerateECKey (keyname, desc, challenges);
if (rc)
ring->Lock (rkey);
if (rc)
rc = ring->Save();
}
delete ring;
}
}
return rc;
}
bool ionu_eyering_gen_ec (const char* keyfile, const char* keyname, const char* desc, const unsigned char* rkey)
{
bool rc = false;
if (keyfile && keyname && rkey) {
Keyring* ring = new Keyring (keyfile);
if (ring) {
rc = ring->Unlock (rkey);
if (rc) {
rc = ring->GenerateECKey (keyname, desc);
if (rc)
ring->Lock (rkey);
if (rc)
rc = ring->Save();
}
delete ring;
}
}
return rc;
}
size_t ionu_eyering_ec_encrypt (const char* keyfile, const char* privatekey, const char* publickey,
const unsigned char* rkey, const unsigned char* in,
size_t len, unsigned char* out)
{
size_t bytes = 0;
if (keyfile && privatekey && publickey && rkey && in && out) {
Keyring* ring = new Keyring (keyfile);
if (ring) {
bool rc = ring->Unlock (rkey);
if (rc) {
const Key* prvkey = ring->GetKey (privatekey);
if (prvkey && prvkey->GetType() == Key::EC) {
const Key* pubkey = ring->GetKey (publickey);
if (pubkey && (pubkey->GetType() == Key::EC_PUBLIC || pubkey->GetType() == Key::EC)) {
unsigned char* buff = NULL;
buff = prvkey->ECDHEncrypt (pubkey, in, len, &bytes);
if (buff) {
memcpy (out, buff, bytes);
delete[] buff;
}
}
}
}
delete ring;
}
}
return bytes;
}
size_t ionu_eyering_ec_decrypt (const char* keyfile, const char* privatekey, const char* publickey,
const unsigned char* rkey, const unsigned char* in,
size_t len, unsigned char* out)
{
size_t bytes = 0;
if (keyfile && privatekey && publickey && rkey && in && out) {
Keyring* ring = new Keyring (keyfile);
if (ring) {
bool rc = ring->Unlock (rkey);
if (rc) {
const Key* prvkey = ring->GetKey (privatekey);
if (prvkey && prvkey->GetType() == Key::EC) {
const Key* pubkey = ring->GetKey (publickey);
if (pubkey && (pubkey->GetType() == Key::EC_PUBLIC || pubkey->GetType() == Key::EC)) {
unsigned char* buff = NULL;
buff = prvkey->ECDHDecrypt (pubkey, in, len, &bytes);
if (buff) {
memcpy (out, buff, bytes);
delete[] buff;
}
}
}
}
delete ring;
}
}
return bytes;
}
bool ionu_eyering_add_binkey (const char* keyfile, const char* keyname, const char* desc, int len, const unsigned char* aeskey, const unsigned char* rkey)
{
bool rc = false;
if (keyfile && keyname && aeskey && rkey) {
Keyring* ring = new Keyring (keyfile);
if (ring) {
rc = ring->Unlock (rkey);
if (rc) {
Key* k = new Key (keyname, desc, len, aeskey, Key::GENERIC);
if (k && ring->AddKey (k)) {
rc = ring->Lock (rkey);
if (rc)
rc = ring->Save();
}
}
delete ring;
}
}
return rc;
}
// Add string key
bool ionu_eyering_add_strkey (const char* keyfile, const char* keyname, const char* desc, const char* key, const unsigned char* rkey)
{
bool rc = false;
if (keyfile && keyname && key && rkey) {
int len = static_cast<int>(strlen (key) + 1); // Include null termination
Keyring* ring = new Keyring (keyfile);
if (ring) {
rc = ring->Unlock (rkey);
if (rc) {
Key* k = new Key (keyname, desc, len, (unsigned char*)key, Key::STRING);
if (k && ring->AddKey (k)) {
rc = ring->Lock (rkey);
if (rc)
rc = ring->Save();
}
}
delete ring;
}
}
return rc;
}
char* ionu_eyering_get_keynames (const char* keyfile)
{
char* json = NULL;
if (keyfile) {
Keyring* ring = new Keyring (keyfile);
if (ring) {
std::string cppjson = ring->GetKeyNames();
json = (char*)malloc (cppjson.size() + 1);
sequencelogic::StrCpy (json, cppjson.c_str()); // Protects if malloc failed
delete ring;
}
}
return json;
}
size_t ionu_eyering_pubkey_encrypt (const char* keyfile, const char* keyname,
const unsigned char* rkey, const unsigned char* in, size_t len,
unsigned char* out)
{
size_t bytes = 0;
if (keyfile && keyname && rkey && in && out) {
Keyring* ring = new Keyring (keyfile);
if (ring) {
bool rc = ring->Unlock (rkey);
if (rc) {
const Key* k = ring->GetKey (keyname);
if (k && (k->GetType() == Key::RSA_PUBLIC || k->GetType() == Key::RSA)) {
unsigned char* buff = NULL;
buff = k->PublicKeyEncrypt (in, len, &bytes);
if (buff) {
memcpy (out, buff, bytes);
delete[] buff;
}
}
}
delete ring;
}
}
return bytes;
}
size_t ionu_eyering_privatekey_decrypt (const char* keyfile, const char* keyname,
const unsigned char* rkey, const unsigned char* in, size_t len,
unsigned char* out)
{
size_t bytes = 0;
if (keyfile && keyname && rkey && in && out) {
Keyring* ring = new Keyring (keyfile);
if (ring) {
bool rc = ring->Unlock (rkey);
if (rc) {
const Key* k = ring->GetKey (keyname);
if (k && k->GetType() == Key::RSA) {
unsigned char* buff = NULL;
buff = k->PrivateKeyDecrypt (in, len, &bytes);
if (buff) {
memcpy (out, buff, bytes);
delete[] buff;
}
}
}
delete ring;
}
}
return bytes;
}
size_t ionu_eyering_rsaprivatekey_encrypt (const char* keyfile, const char* keyname,
const unsigned char* rkey, const unsigned char* in, size_t len,
unsigned char* out)
{
size_t bytes = 0;
if (keyfile && keyname && rkey && in && out) {
Keyring* ring = new Keyring (keyfile);
if (ring) {
bool rc = ring->Unlock (rkey);
if (rc) {
const Key* k = ring->GetKey (keyname);
if (k && k->GetType() == Key::RSA) {
unsigned char* buff = NULL;
buff = k->RSAPrivateKeyEncrypt (in, len, &bytes);
if (buff) {
memcpy (out, buff, bytes);
delete[] buff;
}
}
}
delete ring;
}
}
return bytes;
}
size_t ionu_eyering_rsapublickey_decrypt (const char* keyfile, const char* keyname,
const unsigned char* rkey, const unsigned char* in, size_t len,
unsigned char* out)
{
size_t bytes = 0;
if (keyfile && keyname && rkey && in && out) {
Keyring* ring = new Keyring (keyfile);
if (ring) {
bool rc = ring->Unlock (rkey);
if (rc) {
const Key* k = ring->GetKey (keyname);
if (k && k->GetType() == Key::RSA) {
unsigned char* buff = NULL;
buff = k->RSAPublicKeyDecrypt (in, len, &bytes);
if (buff) {
memcpy (out, buff, bytes);
delete[] buff;
}
}
}
delete ring;
}
}
return bytes;
}
size_t ionu_eyering_ecdh_decrypt (const char* keyfile, const char* keyname,
const unsigned char* rkey, const char* peer,
const unsigned char* in, size_t len, unsigned char* out)
{
size_t bytes = 0;
if (keyfile && keyname && peer && rkey && in && out) {
Keyring* ring = new Keyring (keyfile);
if (ring) {
bool rc = ring->Unlock (rkey);
if (rc) {
const Key* k = ring->GetKey (keyname);
if (k && k->GetType() == Key::EC) {
unsigned char* buff = NULL;
Key* peerkey = new Key ("peer", "ECDH", peer, Key::EC_PUBLIC);
buff = k->ECDHDecrypt (peerkey, in, len, &bytes);
if (buff) {
memcpy (out, buff, bytes);
delete[] buff;
}
}
}
delete ring;
}
}
return bytes;
}
size_t ionu_eyering_privatekey_sign (const char* keyfile, const char* keyname,
const unsigned char* rkey, const unsigned char* tbs, size_t tbslen,
unsigned char* sig)
{
size_t bytes = 0;
if (keyfile && keyname && rkey && tbs && sig) {
Keyring* ring = new Keyring (keyfile);
if (ring) {
bool rc = ring->Unlock (rkey);
if (rc) {
const Key* k = ring->GetKey (keyname);
if (k && k->GetType() == Key::RSA) {
unsigned char* buff = NULL;
buff = k->PrivateKeySign (tbs, tbslen, &bytes);
if (buff) {
memcpy (sig, buff, bytes);
delete[] buff;
}
}
}
delete ring;
}
}
return bytes;
}
bool ionu_eyering_publickey_verify (const char* keyfile, const char* keyname,
const unsigned char* rkey, const unsigned char* tbs, size_t tbslen,
unsigned char* sig, size_t siglen)
{
bool rc = false;
if (keyfile && keyname && rkey && tbs && sig) {
Keyring* ring = new Keyring (keyfile);
if (ring) {
rc = ring->Unlock (rkey);
if (rc) {
const Key* k = ring->GetKey (keyname);
if (k && (k->GetType() == Key::RSA_PUBLIC || k->GetType() == Key::RSA)) {
if (k->PublicKeyVerify (sig, siglen, tbs, tbslen))
rc = true;
else
rc = false;
}
}
delete ring;
}
}
return rc;
}
bool ionu_eyering_change_key (const char* keyfile, const unsigned char* oldkey, const unsigned char* newkey)
{
bool rc = false;
if (keyfile && oldkey && newkey) {
Keyring* ring = new Keyring (keyfile);
if (ring) {
rc = ring->Unlock (oldkey);
if (rc)
rc = ring->Lock (newkey);
if (rc)
rc = ring->Save();
delete ring;
}
}
return rc;
}
bool ionu_eyedb_put (const char* dbfile, const unsigned char* TGIkey, const char* collection, const char* key, const char* value)
{
bool rc = false;
if (dbfile && TGIkey && collection && key) {
EyeEncryptedDB* db = new EyeEncryptedDB (dbfile, TGIkey);
rc = db->Put (collection, key, value);
delete db;
}
return rc;
}
char* ionu_eyedb_get (const char* dbfile, const unsigned char* TGIkey, const char* collection, const char* key)
{
char* ret = NULL;
if (dbfile && TGIkey && collection && key) {
EyeEncryptedDB* db = new EyeEncryptedDB (dbfile, TGIkey);
char* val = db->Get (collection, key);
if (val) {
ret = (char*)malloc (strlen (val) + 1);
sequencelogic::StrCpy (ret, val); // Protects if malloc failed
delete[] val;
}
delete db;
}
return ret;
}
bool ionu_eyedb_remove (const char* dbfile, const unsigned char* TGIkey, const char* collection, const char* key)
{
bool rc = false;
if (dbfile && TGIkey && collection) {
EyeEncryptedDB* db = new EyeEncryptedDB (dbfile, TGIkey);
if (key)
rc = db->Remove (collection, key);
else
rc = db->Remove (collection);
delete db;
}
return rc;
}
// Securely clear out memory used for key or other sensitive data
void ionu_clear_memory (volatile void* mem, size_t len)
{
if (mem)
return sequencelogic::MemSet (mem, 0, len);
}
// return 0 (null/empty) to 1.0 (highest strength)
double ionu_password_strength (const char* clearPassword)
{
if (clearPassword)
return sequencelogic::PassWordStrength (clearPassword);
else
return false;
}
// Derive PBKDF2 key (256 bits) from user password
bool ionu_derive_key (const char* clearPassword, unsigned char* key)
{
if (clearPassword && key)
return sequencelogic::DeriveKey (clearPassword, key);
else
return false;
}
// Derive the user key (256 bits) from the password and cg half key
bool ionu_derive_userkey (const char* clearPassword, unsigned char* userkey, const unsigned char* halfkey)
{
if (clearPassword && userkey && halfkey)
return sequencelogic::DeriveUserKey (clearPassword, userkey, halfkey);
else
return false;
}
// Derive CG key (512 bits: PBKDF2 key plus CG half key)
bool ionu_derive_cgkey(const char* clearPassword, unsigned char* key)
{
if (clearPassword && key)
return sequencelogic::GenerateCGKey (clearPassword, (unsigned char*)key, (unsigned char*)(key + SL_AES_KEY_LEN));
else
return false;
}
// Validate the users password with CG key (512 bits)
bool ionu_validate_cgkey(const char* clearPassword, const unsigned char* key)
{
if (clearPassword && key)
return (sequencelogic::ValidateCGKey (clearPassword, (unsigned char*)key, (unsigned char*)(key + SL_AES_KEY_LEN)));
else
return false;
}
// Validate/create MCF for password - $pbkdf2$2500$ZUfpNd6rSQwYvcwwsk6qKg==$+vrzTteOX1NDMMUWbh6gGzysu2wg8iPB+dwpa0ZtWc8=
char* ionu_slow_hash (const char* password, const char* hash)
{
char* mcf = NULL;
if (password) {
std::string key = hash ? hash : "";
std::string valid = sequencelogic::SlowHash (password, key);
if (valid.size() > 0) {
mcf = (char*)malloc (valid.size() + 1);
sequencelogic::StrCpy (mcf, valid.c_str()); // Protects if malloc failed
}
}
return mcf;
}