/******************************************************************************* * libretroshare/src/pgp: pgphandler.h * * * * libretroshare: retroshare core library * * * * Copyright 2018 Cyril Soler * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public License * * along with this program. If not, see . * * * *******************************************************************************/ #pragma once #include #include #include #include #include #include #include typedef std::string (*PassphraseCallback)(void *data, const char *uid_title, const char *uid_hint, const char *passphrase_info, int prev_was_bad,bool *cancelled) ; class PGPCertificateInfo { public: PGPCertificateInfo() : _trustLvl(0), _validLvl(0), _flags(0), _type(0), _time_stamp(0), _key_index(0) {} std::string _name; std::string _email; std::string _comment; std::set signers; uint32_t _trustLvl; uint32_t _validLvl; uint32_t _flags ; uint32_t _type ; mutable rstime_t _time_stamp ; // last time the key was used (received, used for signature verification, etc) PGPFingerprintType _fpr; /* fingerprint */ // Index to array of keys in the public keyring. Dependign on the specific implementation // of how the keyring is stored, this may be used differently. uint32_t _key_index ; static const uint32_t PGP_CERTIFICATE_FLAG_ACCEPT_CONNEXION = 0x0001 ; static const uint32_t PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE = 0x0002 ; static const uint32_t PGP_CERTIFICATE_FLAG_HAS_SIGNED_ME = 0x0004 ; static const uint32_t PGP_CERTIFICATE_FLAG_UNSUPPORTED_ALGORITHM = 0x0008 ; // set when the key is not RSA, so that RS avoids to use it. static const uint8_t PGP_CERTIFICATE_TRUST_UNDEFINED = 0x00 ; static const uint8_t PGP_CERTIFICATE_TRUST_NEVER = 0x02 ; static const uint8_t PGP_CERTIFICATE_TRUST_MARGINALLY = 0x03 ; static const uint8_t PGP_CERTIFICATE_TRUST_FULLY = 0x04 ; static const uint8_t PGP_CERTIFICATE_TRUST_ULTIMATE = 0x05 ; static const uint8_t PGP_CERTIFICATE_TYPE_UNKNOWN = 0x00 ; static const uint8_t PGP_CERTIFICATE_TYPE_DSA = 0x01 ; static const uint8_t PGP_CERTIFICATE_TYPE_RSA = 0x02 ; }; /// This class offer an abstract pgp handler to be used in RetroShare. class PGPHandler { public: PGPHandler( const std::string& path_to_public_keyring, const std::string& path_to_secret_keyring, const std::string& path_to_trust_database, const std::string& pgp_lock_file) ; virtual ~PGPHandler() ; //=======================================================================================// // Methods that needs to be derived depending on how PGP is implemented // //=======================================================================================// // Removes the given keys from the keyring. Also backup the keyring to a file which name is automatically generated // and given pack for proper display. // virtual bool removeKeysFromPGPKeyring(const std::set& key_ids,std::string& backup_file,uint32_t& error_code) =0; //virtual std::string makeRadixEncodedPGPKey(uint32_t key_index,bool include_signatures) =0; virtual bool availableGPGCertificatesWithPrivateKeys(std::list& ids)=0; virtual bool GeneratePGPCertificate(const std::string& name, const std::string& email, const std::string& passwd, RsPgpId& pgpId, const int keynumbits, std::string& errString) =0; virtual std::string SaveCertificateToString(const RsPgpId& id,bool include_signatures) const=0; /** The caller is in charge of freeing `mem` once finished */ virtual bool exportPublicKey( const RsPgpId& id, unsigned char*& mem_block, size_t& mem_size, bool armoured, bool include_signatures ) const =0; virtual bool exportGPGKeyPair(const std::string& filename,const RsPgpId& exported_key_id) const=0; virtual bool exportGPGKeyPairToString( std::string& data, const RsPgpId& exportedKeyId, bool includeSignatures, std::string& errorMsg ) const =0; // Gets info about the key. Who are the signers, what's the owner's name, etc. // virtual bool getGPGDetailsFromBinaryBlock(const unsigned char *mem,size_t mem_size,RsPgpId& key_id, std::string& name, std::list& signers) const =0; virtual bool importGPGKeyPair(const std::string& filename,RsPgpId& imported_id,std::string& import_error) =0; /** * @param ids list of gpg certificate ids (note, not the actual certificates) */ virtual bool importGPGKeyPairFromString(const std::string& data,RsPgpId& imported_id,std::string& import_error) =0; virtual bool LoadCertificateFromString(const std::string& pem, RsPgpId& gpg_id, std::string& error_string)=0; virtual bool LoadCertificateFromBinaryData(const unsigned char *bin_data,uint32_t bin_data_len, RsPgpId& gpg_id, std::string& error_string)=0; virtual bool encryptTextToFile(const RsPgpId& key_id,const std::string& text,const std::string& outfile) =0; virtual bool decryptTextFromFile(const RsPgpId& key_id,std::string& text,const std::string& encrypted_inputfile) =0; // The client should supply a memory chunk to store the data. The length will be updated to the real length of the data. // virtual bool encryptDataBin(const RsPgpId& key_id,const void *data, const uint32_t len , unsigned char *encrypted_data, unsigned int *encrypted_data_len) =0; virtual bool decryptDataBin(const RsPgpId& key_id,const void *encrypted_data, const uint32_t encrypted_len , unsigned char *data, unsigned int *data_len) =0; virtual bool SignDataBin(const RsPgpId& id, const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen, bool make_raw_signature=false, std::string reason = "") =0; virtual bool privateSignCertificate(const RsPgpId& own_id,const RsPgpId& id_of_key_to_sign) =0; virtual bool VerifySignBin(const void *data, uint32_t data_len, unsigned char *sign, unsigned int sign_len, const PGPFingerprintType& withfingerprint) =0; /** * @brief Get PGP fingerprint for the given key * @param id PGP 64bit key id * @param fp storage for the retrived key fingerpring, the contained value * is meaningfull only if true is returned * @return true if the key was found, false if not */ virtual bool getKeyFingerprint(const RsPgpId& id, RsPgpFingerprint& fp) const=0; virtual bool haveSecretKey(const RsPgpId& id) const =0; // Syncs the keyrings and trust database between memory and disk. The algorithm is: // 1 - lock the keyrings // 2 - compare file modification dates with last writing date // - if file is modified, load it, and merge with memory // 3 - look into memory modification flags // - if flag says keyring has changed, write to disk // virtual bool syncDatabase() =0; //=======================================================================================// // Common methods to PGPHandler // //=======================================================================================// bool getGPGFilteredList(std::list& list,bool (*filter)(const PGPCertificateInfo&) = NULL) const ; bool parseSignature(unsigned char *sign, unsigned int signlen,RsPgpId& issuer_id) ; void setAcceptConnexion(const RsPgpId&,bool) ; void updateOwnSignatureFlag(const RsPgpId& ownId) ; void updateOwnSignatureFlag(const RsPgpId& pgp_id,const RsPgpId& ownId) ; void locked_updateOwnSignatureFlag(PGPCertificateInfo&, const RsPgpId&, PGPCertificateInfo&, const RsPgpId&) ; //bool isKeySupported(const RsPgpId& id) const ; bool privateTrustCertificate(const RsPgpId& id,int valid_level) ; // Write keyring //bool writeSecretKeyring() ; //bool writePublicKeyring() ; const PGPCertificateInfo *getCertificateInfo(const RsPgpId& id) const ; RS_DEPRECATED_FOR(isPgpPubKeyAvailable) bool isGPGId(const RsPgpId &id); bool isGPGSigned(const RsPgpId &id); bool isGPGAccepted(const RsPgpId &id); static void setPassphraseCallback(PassphraseCallback cb) ; static PassphraseCallback passphraseCallback() { return _passphrase_callback ; } /** * @brief Check if a PGP publick key is available * @param id id of the key to check * @return true if the public key for the given id is available, * false otherwise */ bool isPgpPubKeyAvailable(const RsPgpId& id); /** * @brief Convert PGP fingerprint to PGP 64bit id * @param f PGP fingerprint to convert * @return PGP 64bit id extracted from fingerprint */ static RsPgpId pgpIdFromFingerprint(const RsPgpFingerprint& f); // Debug stuff. virtual bool printKeys() const ; protected: void locked_readPrivateTrustDatabase() ; bool locked_writePrivateTrustDatabase() ; bool locked_syncTrustDatabase() ; // Members. // mutable RsMutex pgphandlerMtx ; std::map _public_keyring_map ; // used for fast access to keys. Gives the index in the keyring. std::map _secret_keyring_map ; const std::string _pubring_path ; const std::string _secring_path ; const std::string _trustdb_path ; const std::string _pgp_lock_filename ; bool _pubring_changed ; mutable bool _trustdb_changed ; rstime_t _pubring_last_update_time ; rstime_t _secring_last_update_time ; rstime_t _trustdb_last_update_time ; static PassphraseCallback _passphrase_callback ; };