1183 lines
35 KiB
C++
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;
|
|
}
|