/* Copyright 2021 Grégory Soutadé This file is part of libgourou. libgourou 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. libgourou 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 libgourou. If not, see . */ #ifndef _DRMPROCESSORCLIENT_H_ #define _DRMPROCESSORCLIENT_H_ #include #include namespace gourou { /** * @brief All fucntions that must be implemented by a client * This allow libgourou to have only few external libraries dependencies * and improve code portability */ class DigestInterface { public: /** * @brief Create a digest handler * * @param digestName Digest name to instanciate */ virtual void* createDigest(const std::string& digestName) = 0; /** * @brief Update digest engine with new data * * @param handler Digest handler * @param data Data to digest * @param length Length of data */ virtual void digestUpdate(void* handler, unsigned char* data, unsigned int length) = 0; /** * @brief Finalize digest with remained buffered data and destroy handler * * @param handler Digest handler * @param digestOut Digest result (buffer must be pre allocated with right size) */ virtual void digestFinalize(void* handler, unsigned char* digestOut) = 0; /** * @brief Global digest function * * @param digestName Digest name to instanciate * @param data Data to digest * @param length Length of data * @param digestOut Digest result (buffer must be pre allocated with right size) */ virtual void digest(const std::string& digestName, unsigned char* data, unsigned int length, unsigned char* digestOut) = 0; }; class RandomInterface { public: /** * @brief Generate random bytes * * @param bytesOut Buffer to fill with random bytes * @param length Length of bytesOut */ virtual void randBytes(unsigned char* bytesOut, unsigned int length) = 0; }; class HTTPInterface { public: /** * @brief Send HTTP (GET or POST) request * * @param URL HTTP URL * @param POSTData POST data if needed, if not set, a GET request is done * @param contentType Optional content type of POST Data * @param responseHeaders Optional Response headers of HTTP request * @param fd Optional file descriptor to write request result * @param resume false if target file should be truncated, true to try resume download (works only in combination with a valid fd) * * @return data of HTTP response */ virtual std::string sendHTTPRequest(const std::string& URL, const std::string& POSTData=std::string(""), const std::string& contentType=std::string(""), std::map* responseHeaders=0, int fd=0, bool resume=false) = 0; }; class RSAInterface { public: enum RSA_KEY_TYPE { RSA_KEY_PKCS12 = 0, RSA_KEY_PKCS8, RSA_KEY_X509 }; /** * @brief Encrypt data with RSA private key. Data is padded using PKCS1.5 * * @param RSAKey RSA key in binary form * @param RSAKeyLength RSA key length * @param keyType Key type * @param password Optional password for RSA PKCS12 certificate * @param data Data to encrypt * @param dataLength Data length * @param res Encryption result (pre allocated buffer) */ virtual void RSAPrivateEncrypt(const unsigned char* RSAKey, unsigned int RSAKeyLength, const RSA_KEY_TYPE keyType, const std::string& password, const unsigned char* data, unsigned dataLength, unsigned char* res) = 0; /** * @brief Decrypt data with RSA private key. Data is padded using PKCS1.5 * * @param RSAKey RSA key in binary form * @param RSAKeyLength RSA key length * @param keyType Key type * @param password Optional password for RSA PKCS12 certificate * @param data Data to encrypt * @param dataLength Data length * @param res Encryption result (pre allocated buffer) */ virtual void RSAPrivateDecrypt(const unsigned char* RSAKey, unsigned int RSAKeyLength, const RSA_KEY_TYPE keyType, const std::string& password, const unsigned char* data, unsigned dataLength, unsigned char* res) = 0; /** * @brief Encrypt data with RSA public key. Data is padded using PKCS1.5 * * @param RSAKey RSA key in binary form * @param RSAKeyLength RSA key length * @param keyType Key type * @param password Optional password for RSA PKCS12 certificate * @param data Data to encrypt * @param dataLength Data length * @param res Encryption result (pre allocated buffer) */ virtual void RSAPublicEncrypt(const unsigned char* RSAKey, unsigned int RSAKeyLength, const RSA_KEY_TYPE keyType, const unsigned char* data, unsigned dataLength, unsigned char* res) = 0; /** * @brief Generate RSA key. Expnonent is fixed (65537 / 0x10001) * * @param keyLengthBits Length of key (in bits) to generate * * @return generatedKey */ virtual void* generateRSAKey(int keyLengthBits) = 0; /** * @brief Destroy key previously generated * * @param handler Key to destroy */ virtual void destroyRSAHandler(void* handler) = 0; /** * @brief Extract public key (big number) from RSA handler * * @param handler RSA handler (generated key) * @param keyOut Pre allocated buffer (if *keyOut != 0). If *keyOut is 0, memory is internally allocated (must be freed) * @param keyOutLength Length of result */ virtual void extractRSAPublicKey(void* handler, unsigned char** keyOut, unsigned int* keyOutLength) = 0; /** * @brief Extract private key (big number) from RSA handler * * @param handler RSA handler (generated key) * @param keyOut Pre allocated buffer (if *keyOut != 0). If *keyOut is 0, memory is internally allocated (must be freed) * @param keyOutLength Length of result */ virtual void extractRSAPrivateKey(void* handler, unsigned char** keyOut, unsigned int* keyOutLength) = 0; /** * @brief Extract certificate from PKCS12 blob * * @param RSAKey RSA key in binary form * @param RSAKeyLength RSA key length * @param keyType Key type * @param password Optional password for RSA PKCS12 certificate * @param certOut Result certificate * @param certOutLength Result certificate length */ virtual void extractCertificate(const unsigned char* RSAKey, unsigned int RSAKeyLength, const RSA_KEY_TYPE keyType, const std::string& password, unsigned char** certOut, unsigned int* certOutLength) = 0; }; class CryptoInterface { public: enum CRYPTO_ALGO { ALGO_AES=0, ALGO_RC4 }; enum CHAINING_MODE { CHAIN_ECB=0, CHAIN_CBC }; /** * @brief Do encryption. If length of data is not multiple of block size, PKCS#5 padding is done * * @param algo Algorithm to use * @param chaining Chaining mode * @param key AES key * @param keyLength AES key length * @param iv IV key * @param ivLength IV key length * @param dataIn Data to encrypt * @param dataInLength Data length * @param dataOut Encrypted data * @param dataOutLength Length of encrypted data */ virtual void encrypt(CRYPTO_ALGO algo, CHAINING_MODE chaining, const unsigned char* key, unsigned int keyLength, const unsigned char* iv, unsigned int ivLength, const unsigned char* dataIn, unsigned int dataInLength, unsigned char* dataOut, unsigned int* dataOutLength) = 0; /** * @brief Init encryption * * @param chaining Chaining mode * @param key Key * @param keyLength Key length * @param iv Optional IV key * @param ivLength Optional IV key length * * @return AES handler */ virtual void* encryptInit(CRYPTO_ALGO algo, CHAINING_MODE chaining, const unsigned char* key, unsigned int keyLength, const unsigned char* iv=0, unsigned int ivLength=0) = 0; /** * @brief Encrypt data * * @param handler Crypto handler * @param dataIn Data to encrypt * @param dataInLength Data length * @param dataOut Encrypted data * @param dataOutLength Length of encrypted data */ virtual void encryptUpdate(void* handler, const unsigned char* dataIn, unsigned int dataInLength, unsigned char* dataOut, unsigned int* dataOutLength) = 0; /** * @brief Finalize encryption (pad and encrypt last block if needed) * Destroy handler at the end * * @param handler Crypto handler * @param dataOut Last block of encrypted data * @param dataOutLength Length of encrypted data */ virtual void encryptFinalize(void* handler, unsigned char* dataOut, unsigned int* dataOutLength) = 0; /** * @brief Do decryption. If length of data is not multiple of block size, PKCS#5 padding is done * * @param algo Algorithm to use * @param chaining Chaining mode * @param key AES key * @param keyLength AES key length * @param iv IV key * @param ivLength IV key length * @param dataIn Data to encrypt * @param dataInLength Data length * @param dataOut Encrypted data * @param dataOutLength Length of encrypted data */ virtual void decrypt(CRYPTO_ALGO algo, CHAINING_MODE chaining, const unsigned char* key, unsigned int keyLength, const unsigned char* iv, unsigned int ivLength, const unsigned char* dataIn, unsigned int dataInLength, unsigned char* dataOut, unsigned int* dataOutLength) = 0; /** * @brief Init decryption * * @param chaining Chaining mode * @param key Key * @param keyLength Key length * @param iv IV key * @param ivLength IV key length * * @return AES handler */ virtual void* decryptInit(CRYPTO_ALGO algo, CHAINING_MODE chaining, const unsigned char* key, unsigned int keyLength, const unsigned char* iv=0, unsigned int ivLength=0) = 0; /** * @brief Decrypt data * * @param handler Crypto handler * @param dataIn Data to decrypt * @param dataInLength Data length * @param dataOut Decrypted data * @param dataOutLength Length of decrypted data */ virtual void decryptUpdate(void* handler, const unsigned char* dataIn, unsigned int dataInLength, unsigned char* dataOut, unsigned int* dataOutLength) = 0; /** * @brief Finalize decryption (decrypt last block and remove padding if it is set). * Destroy handler at the end * * @param handler Crypto handler * @param dataOut Last block decrypted data * @param dataOutLength Length of decrypted data */ virtual void decryptFinalize(void* handler, unsigned char* dataOut, unsigned int* dataOutLength) = 0; }; class ZIPInterface { public: /** * @brief Open a zip file and return an handler * * @param path Path of zip file * * @return ZIP file handler */ virtual void* zipOpen(const std::string& path) = 0; /** * @brief Read zip internal file * * @param handler ZIP file handler * @param path Internal path inside zip file * @param result Result buffer * @param decompress If false, don't decompress read data */ virtual void zipReadFile(void* handler, const std::string& path, ByteArray& result, bool decompress=true) = 0; /** * @brief Write zip internal file * * @param handler ZIP file handler * @param path Internal path inside zip file * @param content File content */ virtual void zipWriteFile(void* handler, const std::string& path, ByteArray& content) = 0; /** * @brief Delete zip internal file * * @param handler ZIP file handler * @param path Internal path inside zip file */ virtual void zipDeleteFile(void* handler, const std::string& path) = 0; /** * @brief Close ZIP file handler * * @param handler ZIP file handler */ virtual void zipClose(void* handler) = 0; /** * @brief Inflate algorithm * * @param data Data to inflate * @param result Zipped data * @param wbits Window bits value for libz */ virtual void inflate(gourou::ByteArray& data, gourou::ByteArray& result, int wbits=-15) = 0; /** * @brief Deflate algorithm * * @param data Data to deflate * @param result Unzipped data * @param wbits Window bits value for libz * @param compressionLevel Compression level for libz */ virtual void deflate(gourou::ByteArray& data, gourou::ByteArray& result, int wbits=-15, int compressionLevel=8) = 0; }; class DRMProcessorClient: public DigestInterface, public RandomInterface, public HTTPInterface, \ public RSAInterface, public CryptoInterface, public ZIPInterface {}; } #endif