From 19aacf98a2a2be496126fdbb9b2bba51fd782a65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soutad=C3=A9?= Date: Sat, 18 Dec 2021 17:37:37 +0100 Subject: [PATCH] Make Encryption/Decryption method of DRMProcessorClient generic --- include/drmprocessorclient.h | 85 ++++++++------- utils/drmprocessorclientimpl.cpp | 172 ++++++++++++++++++------------- utils/drmprocessorclientimpl.h | 42 ++++---- 3 files changed, 167 insertions(+), 132 deletions(-) diff --git a/include/drmprocessorclient.h b/include/drmprocessorclient.h index c63a539..fc3b11a 100644 --- a/include/drmprocessorclient.h +++ b/include/drmprocessorclient.h @@ -35,7 +35,7 @@ namespace gourou { public: /** - * @brief Create a digest handler (for now only SHA1 is used) + * @brief Create a digest handler * * @param digestName Digest name to instanciate */ @@ -212,14 +212,20 @@ namespace gourou class CryptoInterface { public: + enum CRYPTO_ALGO { + ALGO_AES=0, + ALGO_RC4 + }; + enum CHAINING_MODE { CHAIN_ECB=0, CHAIN_CBC }; /** - * @brief Do AES encryption. If length of data is not multiple of 16, PKCS#5 padding is done + * @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 @@ -230,52 +236,53 @@ namespace gourou * @param dataOut Encrypted data * @param dataOutLength Length of encrypted data */ - virtual void AESEncrypt(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; + 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 AES CBC encryption + * @brief Init encryption * * @param chaining Chaining mode - * @param key AES key - * @param keyLength AES key length - * @param iv IV key - * @param ivLength IV key length + * @param key Key + * @param keyLength Key length + * @param iv Optional IV key + * @param ivLength Optional IV key length * * @return AES handler */ - virtual void* AESEncryptInit(CHAINING_MODE chaining, - const unsigned char* key, unsigned int keyLength, - const unsigned char* iv=0, unsigned int ivLength=0) = 0; + 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 AES handler + * @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 AESEncryptUpdate(void* handler, const unsigned char* dataIn, unsigned int dataInLength, - unsigned char* dataOut, unsigned int* dataOutLength) = 0; + virtual void EncryptUpdate(void* handler, const unsigned char* dataIn, unsigned int dataInLength, + unsigned char* dataOut, unsigned int* dataOutLength) = 0; /** - * @brief Finalize AES encryption (pad and encrypt last block if needed) + * @brief Finalizeencryption (pad and encrypt last block if needed) * Destroy handler at the end * - * @param handler AES handler + * @param handler Crypto handler * @param dataOut Last block of encrypted data * @param dataOutLength Length of encrypted data */ - virtual void AESEncryptFinalize(void* handler, unsigned char* dataOut, unsigned int* dataOutLength) = 0; + virtual void EncryptFinalize(void* handler, unsigned char* dataOut, unsigned int* dataOutLength) = 0; /** - * @brief Do AES decryption. If length of data is not multiple of 16, PKCS#5 padding is done + * @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 @@ -286,47 +293,47 @@ namespace gourou * @param dataOut Encrypted data * @param dataOutLength Length of encrypted data */ - virtual void AESDecrypt(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; + 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 AES decryption + * @brief Init decryption * * @param chaining Chaining mode - * @param key AES key - * @param keyLength AES key length + * @param key Key + * @param keyLength Key length * @param iv IV key * @param ivLength IV key length * * @return AES handler */ - virtual void* AESDecryptInit(CHAINING_MODE chaining, - const unsigned char* key, unsigned int keyLength, - const unsigned char* iv=0, unsigned int ivLength=0) = 0; + 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 AES handler + * @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 AESDecryptUpdate(void* handler, const unsigned char* dataIn, unsigned int dataInLength, - unsigned char* dataOut, unsigned int* dataOutLength) = 0; + virtual void DecryptUpdate(void* handler, const unsigned char* dataIn, unsigned int dataInLength, + unsigned char* dataOut, unsigned int* dataOutLength) = 0; /** - * @brief Finalize AES decryption (decrypt last block and remove padding if it is set). + * @brief Finalize decryption (decrypt last block and remove padding if it is set). * Destroy handler at the end * - * @param handler AES handler + * @param handler Crypto handler * @param dataOut Last block decrypted data * @param dataOutLength Length of decrypted data */ - virtual void AESDecryptFinalize(void* handler, unsigned char* dataOut, unsigned int* dataOutLength) = 0; + virtual void DecryptFinalize(void* handler, unsigned char* dataOut, unsigned int* dataOutLength) = 0; }; diff --git a/utils/drmprocessorclientimpl.cpp b/utils/drmprocessorclientimpl.cpp index 6ae111b..ee70517 100644 --- a/utils/drmprocessorclientimpl.cpp +++ b/utils/drmprocessorclientimpl.cpp @@ -47,23 +47,28 @@ /* Digest interface */ void* DRMProcessorClientImpl::createDigest(const std::string& digestName) { - EVP_MD_CTX *sha_ctx = EVP_MD_CTX_new(); + EVP_MD_CTX *md_ctx = EVP_MD_CTX_new(); const EVP_MD* md = EVP_get_digestbyname(digestName.c_str()); - EVP_DigestInit(sha_ctx, md); - return sha_ctx; + if (EVP_DigestInit(md_ctx, md) != 1) + { + EVP_MD_CTX_free(md_ctx); + return 0; + } + + return md_ctx; } int DRMProcessorClientImpl::digestUpdate(void* handler, unsigned char* data, unsigned int length) { - return EVP_DigestUpdate((EVP_MD_CTX *)handler, data, length); + return (EVP_DigestUpdate((EVP_MD_CTX *)handler, data, length)) ? 0 : -1; } int DRMProcessorClientImpl::digestFinalize(void* handler, unsigned char* digestOut) { int res = EVP_DigestFinal((EVP_MD_CTX *)handler, digestOut, NULL); EVP_MD_CTX_free((EVP_MD_CTX *)handler); - return res; + return (res == 1) ? 0 : -1; } int DRMProcessorClientImpl::digest(const std::string& digestName, unsigned char* data, unsigned int length, unsigned char* digestOut) @@ -283,83 +288,106 @@ void DRMProcessorClientImpl::extractCertificate(const unsigned char* RSAKey, uns } /* Crypto interface */ -void DRMProcessorClientImpl::AESEncrypt(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) +void DRMProcessorClientImpl::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) { - void* handler = AESEncryptInit(chaining, key, keyLength, iv, ivLength); - AESEncryptUpdate(handler, dataIn, dataInLength, dataOut, dataOutLength); - AESEncryptFinalize(handler, dataOut+*dataOutLength, dataOutLength); + void* handler = EncryptInit(algo, chaining, key, keyLength, iv, ivLength); + EncryptUpdate(handler, dataIn, dataInLength, dataOut, dataOutLength); + EncryptFinalize(handler, dataOut+*dataOutLength, dataOutLength); } -void* DRMProcessorClientImpl::AESEncryptInit(CHAINING_MODE chaining, +void* DRMProcessorClientImpl::EncryptInit(CRYPTO_ALGO algo, CHAINING_MODE chaining, + const unsigned char* key, unsigned int keyLength, + const unsigned char* iv, unsigned int ivLength) +{ + EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); + + if (algo == ALGO_AES) + { + switch(keyLength) + { + case 16: + switch(chaining) + { + case CHAIN_ECB: + EVP_EncryptInit(ctx, EVP_aes_128_ecb(), key, iv); + break; + case CHAIN_CBC: + EVP_EncryptInit(ctx, EVP_aes_128_cbc(), key, iv); + break; + default: + EXCEPTION(gourou::CLIENT_BAD_CHAINING, "Unknown chaining mode " << chaining); + } + break; + default: + EVP_CIPHER_CTX_free(ctx); + EXCEPTION(gourou::CLIENT_BAD_KEY_SIZE, "Invalid key size " << keyLength); + } + } + else if (algo == ALGO_RC4) + { + if (keyLength != 16) + { + EVP_CIPHER_CTX_free(ctx); + EXCEPTION(gourou::CLIENT_BAD_KEY_SIZE, "Invalid key size " << keyLength); + } + EVP_DecryptInit(ctx, EVP_rc4(), key, iv); + } + return ctx; +} + +void* DRMProcessorClientImpl::DecryptInit(CRYPTO_ALGO algo, CHAINING_MODE chaining, const unsigned char* key, unsigned int keyLength, const unsigned char* iv, unsigned int ivLength) { EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); - switch(keyLength) + if (algo == ALGO_AES) { - case 16: - switch(chaining) + switch(keyLength) { - case CHAIN_ECB: - EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, iv); - break; - case CHAIN_CBC: - EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv); + case 16: + switch(chaining) + { + case CHAIN_ECB: + EVP_DecryptInit(ctx, EVP_aes_128_ecb(), key, iv); + break; + case CHAIN_CBC: + EVP_DecryptInit(ctx, EVP_aes_128_cbc(), key, iv); + break; + default: + EXCEPTION(gourou::CLIENT_BAD_CHAINING, "Unknown chaining mode " << chaining); + } break; default: - EXCEPTION(gourou::CLIENT_BAD_CHAINING, "Unknown chaining mode " << chaining); + EVP_CIPHER_CTX_free(ctx); + EXCEPTION(gourou::CLIENT_BAD_KEY_SIZE, "Invalid key size " << keyLength); } - break; - default: - EVP_CIPHER_CTX_free(ctx); - EXCEPTION(gourou::CLIENT_BAD_KEY_SIZE, "Invalid key size " << keyLength); } - + else if (algo == ALGO_RC4) + { + if (keyLength != 16) + { + EVP_CIPHER_CTX_free(ctx); + EXCEPTION(gourou::CLIENT_BAD_KEY_SIZE, "Invalid key size " << keyLength); + } + EVP_DecryptInit(ctx, EVP_rc4(), key, iv); + } + return ctx; } -void* DRMProcessorClientImpl::AESDecryptInit(CHAINING_MODE chaining, - const unsigned char* key, unsigned int keyLength, - const unsigned char* iv, unsigned int ivLength) -{ - EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); - - switch(keyLength) - { - case 16: - switch(chaining) - { - case CHAIN_ECB: - EVP_DecryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, iv); - break; - case CHAIN_CBC: - EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv); - break; - default: - EXCEPTION(gourou::CLIENT_BAD_CHAINING, "Unknown chaining mode " << chaining); - } - break; - default: - EVP_CIPHER_CTX_free(ctx); - EXCEPTION(gourou::CLIENT_BAD_KEY_SIZE, "Invalid key size " << keyLength); - } - - return ctx; -} - -void DRMProcessorClientImpl::AESEncryptUpdate(void* handler, const unsigned char* dataIn, unsigned int dataInLength, - unsigned char* dataOut, unsigned int* dataOutLength) +void DRMProcessorClientImpl::EncryptUpdate(void* handler, const unsigned char* dataIn, unsigned int dataInLength, + unsigned char* dataOut, unsigned int* dataOutLength) { EVP_EncryptUpdate((EVP_CIPHER_CTX*)handler, dataOut, (int*)dataOutLength, dataIn, dataInLength); } -void DRMProcessorClientImpl::AESEncryptFinalize(void* handler, - unsigned char* dataOut, unsigned int* dataOutLength) +void DRMProcessorClientImpl::EncryptFinalize(void* handler, + unsigned char* dataOut, unsigned int* dataOutLength) { int len; EVP_EncryptFinal_ex((EVP_CIPHER_CTX*)handler, dataOut, &len); @@ -367,24 +395,24 @@ void DRMProcessorClientImpl::AESEncryptFinalize(void* handler, EVP_CIPHER_CTX_free((EVP_CIPHER_CTX*)handler); } -void DRMProcessorClientImpl::AESDecrypt(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) +void DRMProcessorClientImpl::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) { - void* handler = AESDecryptInit(chaining, key, keyLength, iv, ivLength); - AESDecryptUpdate(handler, dataIn, dataInLength, dataOut, dataOutLength); - AESDecryptFinalize(handler, dataOut+*dataOutLength, dataOutLength); + void* handler = DecryptInit(algo, chaining, key, keyLength, iv, ivLength); + DecryptUpdate(handler, dataIn, dataInLength, dataOut, dataOutLength); + DecryptFinalize(handler, dataOut+*dataOutLength, dataOutLength); } -void DRMProcessorClientImpl::AESDecryptUpdate(void* handler, const unsigned char* dataIn, unsigned int dataInLength, - unsigned char* dataOut, unsigned int* dataOutLength) +void DRMProcessorClientImpl::DecryptUpdate(void* handler, const unsigned char* dataIn, unsigned int dataInLength, + unsigned char* dataOut, unsigned int* dataOutLength) { EVP_DecryptUpdate((EVP_CIPHER_CTX*)handler, dataOut, (int*)dataOutLength, dataIn, dataInLength); } -void DRMProcessorClientImpl::AESDecryptFinalize(void* handler, unsigned char* dataOut, unsigned int* dataOutLength) +void DRMProcessorClientImpl::DecryptFinalize(void* handler, unsigned char* dataOut, unsigned int* dataOutLength) { int len; EVP_DecryptFinal_ex((EVP_CIPHER_CTX*)handler, dataOut, &len); diff --git a/utils/drmprocessorclientimpl.h b/utils/drmprocessorclientimpl.h index 5351fa4..4913b05 100644 --- a/utils/drmprocessorclientimpl.h +++ b/utils/drmprocessorclientimpl.h @@ -73,34 +73,34 @@ public: unsigned char** certOut, unsigned int* certOutLength); /* Crypto interface */ - virtual void AESEncrypt(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); + 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); - virtual void* AESEncryptInit(CHAINING_MODE chaining, - const unsigned char* key, unsigned int keyLength, - const unsigned char* iv=0, unsigned int ivLength=0); + 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); - virtual void AESEncryptUpdate(void* handler, const unsigned char* dataIn, unsigned int dataInLength, + virtual void EncryptUpdate(void* handler, const unsigned char* dataIn, unsigned int dataInLength, unsigned char* dataOut, unsigned int* dataOutLength); - virtual void AESEncryptFinalize(void* handler, unsigned char* dataOut, unsigned int* dataOutLength); + virtual void EncryptFinalize(void* handler, unsigned char* dataOut, unsigned int* dataOutLength); - virtual void AESDecrypt(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); + 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); - virtual void* AESDecryptInit(CHAINING_MODE chaining, - const unsigned char* key, unsigned int keyLength, - const unsigned char* iv=0, unsigned int ivLength=0); + 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); - virtual void AESDecryptUpdate(void* handler, const unsigned char* dataIn, unsigned int dataInLength, - unsigned char* dataOut, unsigned int* dataOutLength); - virtual void AESDecryptFinalize(void* handler, unsigned char* dataOut, unsigned int* dataOutLength); + virtual void DecryptUpdate(void* handler, const unsigned char* dataIn, unsigned int dataInLength, + unsigned char* dataOut, unsigned int* dataOutLength); + virtual void DecryptFinalize(void* handler, unsigned char* dataOut, unsigned int* dataOutLength); /* ZIP Interface */ virtual void* zipOpen(const std::string& path);