// 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 #include #include #include #include #include #include #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(GlobalPolicy->GetMember (POLICY)); if (policies) { for (size_t i = 0; i < policies->GetNumMembers(); ++i) { EyeJSONObject* policy = dynamic_cast(policies->GetMember (i)); if (policy && policy->GetType() == JSON_OBJECT) { EyeJSONNode* item = policy->GetMember (POLICYNAME); if (item && strcmp (dynamic_cast(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(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(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(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; }