/* Copyright (c) 2013-2015 IONU Security Inc. All rights reserved. * Copyright (c) 2016 Sequence Logic Inc. All rights reserved. * * C interface wrappers to the libeye */ #ifndef eyeinterface_h #define eyeinterface_h #ifndef WIN32 #include #endif #ifndef LIBEYE_DLL #ifdef WIN32 # ifdef DLLEXPORT # define LIBEYE_DLL __declspec(dllexport) # else # define LIBEYE_DLL __declspec(dllimport) # endif #else #define LIBEYE_DLL #endif #endif #ifdef __cplusplus #define USE_EXTERN_C #endif #ifdef USE_EXTERN_C extern "C" { #endif enum EYE_LOG_LEVEL { IONU_FATAL = 1, IONU_ERROR = 2, IONU_WARN = 3, IONU_INFO = 4, IONU_DEBUG = 5, IONU_VERBOSE = 6 }; enum EYE_LOG_SINK { IONU_SYSLOG, IONU_CONSOLE }; enum EYE_FILE_LOCK_STATUS { EYE_FILE_LOCK_OK, EYE_FILE_LOCK_ERROR, EYE_FILE_LOCK_TIMEOUT }; enum EYE_FILE_LOCK_TYPE { EYE_FILE_LOCK_READ, EYE_FILE_LOCK_WRITE, EYE_FILE_LOCK_CLEAR }; /** * Configure a file based logger * * @param app Application identifier (e.g. "IM") * @param device Device identifier (e.g. "urn:sl:000000:17C38E5A:C60D:79916D07C42C - Nexus-7") * @param level Minimum log level, only this and higher priority messages logged * @param logfile Name of the local log file * @return true if successful */ LIBEYE_DLL bool ionu_configfilelog (const char* app, const char* device, enum EYE_LOG_LEVEL level, const char* logfile); /** * Configure a console based logger * * @param app Application identifier (e.g. "IM") * @param device Device identifier (e.g. "urn:sl:000000:17C38E5A:C60D:79916D07C42C - Nexus-7") * @param level Minimum log level, only this and higher priority messages logged * @param sink Log to console or platform specific logger * @return true if successful */ LIBEYE_DLL bool ionu_configlog (const char* app, const char* device, enum EYE_LOG_LEVEL level, enum EYE_LOG_SINK sink); /** * Log a message * * @param level Log level, IONU_ERROR, IONU_WARN... * @param msg Message string */ LIBEYE_DLL void ionu_log (enum EYE_LOG_LEVEL level, const char* msg); /** * Close the logger and any open log files * * @return true if successful */ LIBEYE_DLL bool ionu_closelog (); /** * Install policy array from JSON string, replaces existing policy if already loaded * * @param policy JSON with "policy" array of objects * @return true if the policy array was installed */ LIBEYE_DLL bool ionu_policy_install (const char* jsonPolicy); /** * Unistall policy array from memory * * @return true if the policy array was uninstalled */ LIBEYE_DLL bool ionu_policy_uninstall (); /** * Look for the "policyName" in the installed policy array * * @param name policyName to return * @return JSON string for named policy or NULL */ LIBEYE_DLL char* ionu_policy_check (const char* policyName); // Eye Container functions ---------------------------------------------------- /** Lock an eyefile for read/write access Read access is cooperative, write access is exclusive @param filename - path to the file @param id - identifier for the lock, typically thread id @return status of lock acquisition */ enum EYE_FILE_LOCK_STATUS ionu_eyefile_lock (const char* filename, const char* id, enum EYE_FILE_LOCK_TYPE ltype); // Eye Ring functions --------------------------------------------------------- /** * Create a key ring * * @param keyfile Keyring filename * @param ring name of the key ring * @param desc description of the key ring (e.g. "Device key ring"), optional * @param rkey ring key - 256 bit (32 byte) key used to lock the key ring * @return true if the key ring was created and saved successfully */ bool ionu_eyering_create (const char* keyfile, const char* ring, const char* desc, const unsigned char* rkey); /** * Get a JSON array of the key names in clear text * * @param keyfile Keyring filename * @return json array or NULL (if not valid) */ char* ionu_eyering_get_keynames (const char* keyfile); /** * Add a string key to the specified key ring, can be used to store anything * * @param keyfile Keyring filename * @param keyname name of the key * @param desc description of the key (e.g. "PMO public key"), optional * @param key nul terminated string data * @param rkey ring key - 256 bit (32 byte) key used to lock the key ring * @return true if the key ring was unlocked, and the named key was added (or updated if already in keyring) */ bool ionu_eyering_add_strkey (const char* keyfile, const char* keyname, const char* desc, const char* key, const unsigned char* rkey); /** * Add a generic binary key to the specified key ring * * @param keyfile Keyring filename * @param keyname name of the key * @param desc description of the key (e.g. "AES 256 bit"), optional * @param len number of bytes in key * @param aes key data * @param rkey ring key - 256 bit (32 byte) key used to lock the key ring * @return true if the key ring was unlocked, and the named key was added (or updated if already in keyring) */ bool ionu_eyering_add_binkey (const char* keyfile, const char* keyname, const char* desc, int len, const unsigned char* aes, const unsigned char* rkey); /** * Add an RSA key to the specified key ring * * @param keyfile Keyring filename * @param keyname name of the key * @param desc description of the key (e.g. "My private key"), optional * @param pem PEM encoded RSA key - can be either public or private key * @param rkey ring key - 256 bit (32 byte) key used to lock the key ring * @return true if the key ring was unlocked, and the named key was added (or updated if already in keyring) */ bool ionu_eyering_add_rsakey (const char* keyfile, const char* keyname, const char* desc, const char* pem, const unsigned char* rkey); /** * Get named key from the specified key ring * * @param keyfile Keyring filename * @param keyname name of the key * @param key key data return, caller must ensure buffer is sufficient size (use get_key_len if you don't know) * @param rkey ring key - 256 bit (32 byte) key used to lock the key ring * @return true if the key ring was unlocked, and the named key was found */ bool ionu_eyering_get_key (const char* keyfile, const char* keyname, unsigned char* key, const unsigned char* rkey); /** * Get named key as a string from the specified key ring * * @param keyfile Keyring filename * @param keyname name of the key * @param rkey ring key - 256 bit (32 byte) key used to lock the key ring * @return string if key was found or NULL if the named key was not found */ char* ionu_eyering_get_strkey (const char* keyfile, const char* keyname, const unsigned char* rkey); /** * Get the length in bytes of named key from the specified key ring * * @param keyfile Keyring filename * @param keyname name of the key * @param rkey ring key - 256 bit (32 byte) key used to lock the key ring * @return number of bytes for the key */ int ionu_eyering_get_key_len (const char* keyfile, const char* keyname, const unsigned char* rkey); /** * Remove the named key from the specified key ring * * @param keyfile Keyring filename * @param keyname name of the key * @return true if the key ring was unlocked, key found, and saved with the key removed */ bool ionu_eyering_remove_key (const char* keyfile, const char* keyname, const unsigned char* rkey); /** * Get the public key from the named RSA private key from the specified key ring * * @param keyfile Keyring filename * @param keyname name of the RSA private key * @param rkey ring key - 256 bit (32 byte) key used to lock the key ring * @return PEM encoded public key or NULL */ char* ionu_eyering_get_pubkey (const char* keyfile, const char* keyname, const unsigned char* rkey); /** * Encrypt data using the specified public key * * @param keyfile Keyring filename * @param keyname name of the RSA public or private key * @param rkey ring key - 256 bit (32 byte) key used to lock the key ring * @param in plain text (214 byte maximum with EME-OAEP padding) * @param len length of plain text * @param out cipher text, which is 256 bytes (2048 bit RSA / 8) * @return number of bytes in cipher text (0 will be returned for failure) */ 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); /** * Decrypt data using the specified private key * * @param keyfile Keyring filename * @param keyname name of the RSA private key * @param rkey ring key - 256 bit (32 byte) key used to lock the key ring * @param in cipher text * @param len length of cipher text (2048/8 = 256) * @param out plain text * @return number of bytes in cipher text (0 will be returned for failure) */ 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); /** * Sign data using the specified private key * * @param keyfile Keyring filename * @param keyname name of the RSA private key * @param rkey ring key - 256 bit (32 byte) key used to lock the key ring * @param tbs data to be signed * @param tbslen length of data to be signed * @param sig signature * @return number of bytes in signature (0 will be returned for failure) */ 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); /** * Verify signatire using the specified public key * * @param keyfile Keyring filename * @param keyname name of the RSA private key * @param rkey ring key - 256 bit (32 byte) key used to lock the key ring * @param tbs data to be signed * @param tbslen length of data to be signed * @param sig signature * @param siglen length of signature * @return true if verified */ 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); // These are unsecure and misnamed, provided for compatibility with the libionu version for CG token exchange size_t ionu_eyering_rsaprivatekey_encrypt (const char* keyfile, const char* keyname, const unsigned char* rkey, const unsigned char* in, size_t inlen, unsigned char* out); size_t ionu_eyering_rsapublickey_decrypt (const char* keyfile, const char* keyname, const unsigned char* rkey, const unsigned char* in, size_t inlen, unsigned char* out); /** * Generate deterministic 2048 RSA keypair using a JSON challenge string to seed a DRBG, such that * given same challenges will produce the same key, and add the private key to the ring * ["userid","answer1","answer2","answer3"] * * @param keyfile Keyring filename * @param keyname name of the RSA private key * @param desc description of the key (e.g. "My private key"), optional * @param chalenge JSON array as an ordered string of challenge response and userid * @param rkey ring key - 256 bit (32 byte) key used to lock the key ring * @return true if key was successfully created and added to the keyring */ bool ionu_eyering_gen_rsa_challenge (const char* keyfile, const char* keyname, const char* desc, const char* challenges, const unsigned char* rkey); /** * Generate random 2048 bit RSA keypair and add the private key to the keyring, use * ionu_eyering_get_pubkey(keyfile, keyname, key) to get the matching public key * * @param keyfile Keyring filename * @param keyname name of the RSA private key * @param desc description of the key (e.g. "My private key"), optional * @param rkey ring key - 256 bit (32 byte) key used to lock the key ring * @return true if the key ring was unlocked, and the named key was generated and added */ bool ionu_eyering_gen_rsa (const char* keyfile, const char* keyname, const char* desc, const unsigned char* rkey); /** * Generate deterministic 2048 bit RSA keypair and add the private key to the keyring * * Calling sequence is (1. pre-provision, 2. provision and get salt, 3. discard secret, use salt and challenge): * 1) ionu_eyering_gen_rsa_secret_challenge (keyfile, keyname, desc, NULL, "secret", NULL, rkey); * 2) char* sssalt = ionu_eyering_gen_rsa_secret_salt (keyfile, keyname, desc, "[sequencelogic::json]", "secret", rkey); * 3) ionu_eyering_gen_rsa_secret_challenge (keyfile, keyname, desc, "[sequencelogic::json]", NULL, sssalt, rkey); * * @param keyfile Keyring filename * @param keyname name of the RSA private key * @param desc description of the key (e.g. "My private key"), optional * @param chalenge JSON array as an ordered string of challenge response and userid * @param secret Secret string to be used to seed DRBG * @param salt Salt to be combined with challenges to seed DRBG (base64 or hex encoded) * @param rkey ring key - 256 bit (32 byte) key used to lock the key ring * @return true if the key ring was unlocked, and the named key was generated and added */ 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); /** * Generate deterministic 2048 bit RSA keypair and add the private key to the keyring * * @param keyfile Keyring filename * @param keyname name of the RSA private key * @param desc description of the key (e.g. "My private key"), optional * @param chalenge JSON array as an ordered string of challenge response and userid * @param secret Secret string to be used to seed DRBG * @param rkey ring key - 256 bit (32 byte) key used to lock the key ring * @return salt for subsequent use without secret (base64 encoded) */ 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); /** * Generate random 2048 bit RSA keypair and and return the pair in separate buffers PEM encoded * * @param keyfile Keyring filename * @param private PEM encoded private key * @param public PEM encoded public key * @return true if the key pair was successfully generated */ bool ionu_eyering_gen_rsa_pair (char* private_pem, char* public_pem); /** * Generate deterministic 2048 bit RSA keypair and and return the pair in separate buffers PEM encoded * * @param keyfile Keyring filename * @param chalenge json array as an ordered string of challenge response and userid * @param private PEM encoded private key * @param public PEM encoded public key * @return true if the key pair was successfully generated */ bool ionu_eyering_gen_rsa_challenge_pair (const char* challenges, char* private_pem, char* public_pem); /** * Generate deterministic 521 bit EC keypair using a json challenge string to seed a DRBG, such that * given same challenges will produce the same key, and add the private key to the ring * ["userid","answer1","answer2","answer3"] * * @param chalenge json array as an ordered string of challenge response and userid * @return true if key was successfully created and added to the keyring */ bool ionu_eyering_gen_ec_challenge (const char* keyfile, const char* keyname, const char* desc, const char* challenges, const unsigned char* rkey); /** * Generate random 521 bit EC keypair and add the private key to the keyring, use * ionu_eyering_get_pubkey(keyfile, keyname, key) to get the matching public key * * @param keyfile Keyring filename * @param keyname name of the RSA private key * @param desc description of the key (e.g. "My private key"), optional * @param rkey ring key - 256 bit (32 byte) key used to lock the key ring * @return true if the key ring was unlocked, and the named key was generated and added */ bool ionu_eyering_gen_ec (const char* keyfile, const char* keyname, const char* desc, const unsigned char* rkey); /** * Generate deterministic 521 bit EC keypair and and return the pair in separate buffers PEM encoded * * @param keyfile Keyring filename * @param chalenge json array as an ordered string of challenge response and userid * @param private PEM encoded private key * @param public PEM encoded public key * @return true if the key pair was successfully generated */ bool ionu_eyering_gen_ec_challenge_pair (const char* challenges, char* private_pem, char* public_pem); /** * Encrypt data using the specified EC keys * * @param keyfile Keyring filename * @param private name of the EC private key * @param public name of the EC private key * @param rkey ring key - 256 bit (32 byte) key used to lock the key ring * @param in plain text * @param len length of plain text * @param out cipher text, which is 256 bytes (2048 bit RSA / 8) * @return number of bytes in cipher text (0 will be returned for failure) */ 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); /** * Decrypt data using the specified EC keys * * @param keyfile Keyring filename * @param keyname name of the RSA private key * @param rkey ring key - 256 bit (32 byte) key used to lock the key ring * @param in cipher text * @param len length of cipher text (2048/8 = 256) * @param out plain text * @return number of bytes in cipher text (0 will be returned for failure) */ 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); /** * Change the key used to encrypt Keyring * * @param keyfile Keyring filename * @param oldkey Existing AES key * @param newkey New AES key * @return true if successful */ bool ionu_eyering_change_key (const char* keyfile, const unsigned char* oldkey, const unsigned char* newkey); // Database functions ---------------------------------------------------------- /** * Put a key value pair (INSERT OR REPLACE) in the specified table (CREATE TABLE IF NOT EXISTS) * * @param dbfile SQLite database filename * @param TGIkey AES key used to encrypt database * @param table name of the table * @param key name of the key within table * @param value data to store * @return true if successful */ bool ionu_eyedb_put (const char* dbfile, const unsigned char* TGIkey, const char* table, const char* key, const char* value); /** * Get a value specified by key and table * * @param dbfile SQLite database filename * @param TGIkey AES key used to encrypt database * @param table name of the table * @param key name of the key within table * @return value if successful, NULL if not */ char* ionu_eyedb_get (const char* dbfile, const unsigned char* TGIkey, const char* table, const char* key); /** * Remove a value specified by key and table * * @param dbfile SQLite database filename * @param TGIkey AES key used to encrypt database * @param table name of the table * @param key name of the key within table * @return true if successful */ bool ionu_eyedb_remove (const char* dbfile, const unsigned char* TGIkey, const char* table, const char* key); // Utility functions ---------------------------------------------------------- /** * Securely clear out memory used for key or other sensitive data * * @param mem location of memory to clear * @param len number of bytes to clear */ LIBEYE_DLL void ionu_clear_memory (volatile void* mem, size_t len); /** * Base64 encode and decode */ LIBEYE_DLL bool ionu_base64_encode (const unsigned char *input, size_t len, char *output ); LIBEYE_DLL size_t ionu_base64_decode (const char *input, unsigned char *output); /** * Generate a digest for a message * * @param digest name of the message digest algorithm (e.g. md5, sha1, sha256...) * @param msg message data * @param len number of bytes in message * @return hex string containing digest, caller must free, NULL if failed */ LIBEYE_DLL char* ionu_digest_msg (const char* digest, const unsigned char* msg, size_t len); /** * Generate a digest for a file * * @param digest name of the message digest algorithm (e.g. md5, sha1, sha256...) * @param filename name of the file * @return hex string containing digest, caller must free, NULL if failed */ LIBEYE_DLL char* ionu_digest_file (const char* digest, const char* filename); /** * Generate an HMAC for a message * * @param key key data * @param klen number of bytes in key * @param msg message data * @param mlen number of bytes in message * @return hex string containing HMAC, caller must free, NULL if failed */ LIBEYE_DLL char* ionu_hmac_msg (const unsigned char* key, size_t klen, const unsigned char* msg, size_t mlen); /** * libionu compatibility functions */ LIBEYE_DLL size_t ionu_symmetric_encrypt_buffer_pass (const char* passphrase, const unsigned char* in, size_t inlen, unsigned char* out); LIBEYE_DLL size_t ionu_symmetric_decrypt_buffer_pass (const char* passphrase, const unsigned char* in, size_t inlen, unsigned char* out); LIBEYE_DLL size_t ionu_symmetric_encrypt_buffer (const unsigned char* aes, const unsigned char* in, size_t inlen, unsigned char* out, const unsigned char* iv); LIBEYE_DLL size_t ionu_symmetric_decrypt_buffer (const unsigned char* aes, const unsigned char* in, size_t inlen, unsigned char* out, const unsigned char* iv); LIBEYE_DLL size_t ionu_private_key_decrypt (const char* pem, const unsigned char* in, size_t inlen, unsigned char* out); LIBEYE_DLL size_t ionu_public_key_encrypt (const char* pem, const unsigned char* in, size_t inlen, unsigned char* out); LIBEYE_DLL size_t ionu_public_key_decrypt (const char* pem, const unsigned char* in, size_t inlen, unsigned char* out); LIBEYE_DLL size_t ionu_private_key_encrypt (const char* pem, const unsigned char* in, size_t inlen, unsigned char* out); /** * Fast algorithm to check relative password strength * * @param password clear text password * @return 0.0 (null/empty) to 1.0 (highest strength) */ LIBEYE_DLL double ionu_password_strength(const char* clearPassword); /** * Slow PBKDF2 algorithm to derive key from user password * * @param password clear text password * @param key 256 bit (32 byte) TGI key * @return true if generation succeeded */ LIBEYE_DLL bool ionu_derive_key (const char* clearPassword, unsigned char* key); /** * Fast algorithm to derive key from user password and cloudguard half key * * @param password clear text password * @param userkey 256 bit (32 byte) user key * @param halfkey 256 bit (32 byte) cloud guard half key * @return true if generation succeeded */ LIBEYE_DLL bool ionu_derive_userkey (const char* clearPassword, unsigned char* userkey, const unsigned char* halfkey); /** * Slow PBKDF2 algorithm to derive key from user password and random cloudguard half key * * @param password clear text password * @param key 512 bit (64 byte) cloudguard key and half key * @return true if generation succeeded */ LIBEYE_DLL bool ionu_derive_cgkey(const char* clearPassword, unsigned char* key); /** * Slow PBKDF2 algorithm to validate user password with cloudguard 512 bits * * @param password clear text password * @param key 512 bit (64 byte) cloudguard key and half key * @return true if generation succeeded */ LIBEYE_DLL bool ionu_validate_cgkey(const char* clearPassword, const unsigned char* key); /** * Validate/create MCF for password - $pbkdf2$2500$ZUfpNd6rSQwYvcwwsk6qKg==$+vrzTteOX1NDMMUWbh6gGzysu2wg8iPB+dwpa0ZtWc8= * * @param password clear text password * @param hash base64 pbkdf2+2500 or MCF formatted value, NULL or "" for creation of new hash * @return NULL if failed to validate or MCF formatted string */ LIBEYE_DLL char* ionu_slow_hash (const char* password, const char* hash); #ifdef USE_EXTERN_C } #endif #endif