Make Encryption/Decryption method of DRMProcessorClient generic

This commit is contained in:
Grégory Soutadé 2021-12-18 17:37:37 +01:00
parent a751327dab
commit 19aacf98a2
3 changed files with 167 additions and 132 deletions

View File

@ -35,7 +35,7 @@ namespace gourou
{ {
public: public:
/** /**
* @brief Create a digest handler (for now only SHA1 is used) * @brief Create a digest handler
* *
* @param digestName Digest name to instanciate * @param digestName Digest name to instanciate
*/ */
@ -212,14 +212,20 @@ namespace gourou
class CryptoInterface class CryptoInterface
{ {
public: public:
enum CRYPTO_ALGO {
ALGO_AES=0,
ALGO_RC4
};
enum CHAINING_MODE { enum CHAINING_MODE {
CHAIN_ECB=0, CHAIN_ECB=0,
CHAIN_CBC 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 chaining Chaining mode
* @param key AES key * @param key AES key
* @param keyLength AES key length * @param keyLength AES key length
@ -230,52 +236,53 @@ namespace gourou
* @param dataOut Encrypted data * @param dataOut Encrypted data
* @param dataOutLength Length of encrypted data * @param dataOutLength Length of encrypted data
*/ */
virtual void AESEncrypt(CHAINING_MODE chaining, virtual void Encrypt(CRYPTO_ALGO algo, CHAINING_MODE chaining,
const unsigned char* key, unsigned int keyLength, const unsigned char* key, unsigned int keyLength,
const unsigned char* iv, unsigned int ivLength, const unsigned char* iv, unsigned int ivLength,
const unsigned char* dataIn, unsigned int dataInLength, const unsigned char* dataIn, unsigned int dataInLength,
unsigned char* dataOut, unsigned int* dataOutLength) = 0; unsigned char* dataOut, unsigned int* dataOutLength) = 0;
/** /**
* @brief Init AES CBC encryption * @brief Init encryption
* *
* @param chaining Chaining mode * @param chaining Chaining mode
* @param key AES key * @param key Key
* @param keyLength AES key length * @param keyLength Key length
* @param iv IV key * @param iv Optional IV key
* @param ivLength IV key length * @param ivLength Optional IV key length
* *
* @return AES handler * @return AES handler
*/ */
virtual void* AESEncryptInit(CHAINING_MODE chaining, virtual void* EncryptInit(CRYPTO_ALGO algo, CHAINING_MODE chaining,
const unsigned char* key, unsigned int keyLength, const unsigned char* key, unsigned int keyLength,
const unsigned char* iv=0, unsigned int ivLength=0) = 0; const unsigned char* iv=0, unsigned int ivLength=0) = 0;
/** /**
* @brief Encrypt data * @brief Encrypt data
* *
* @param handler AES handler * @param handler Crypto handler
* @param dataIn Data to encrypt * @param dataIn Data to encrypt
* @param dataInLength Data length * @param dataInLength Data length
* @param dataOut Encrypted data * @param dataOut Encrypted data
* @param dataOutLength Length of encrypted data * @param dataOutLength Length of encrypted data
*/ */
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) = 0; 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 * Destroy handler at the end
* *
* @param handler AES handler * @param handler Crypto handler
* @param dataOut Last block of encrypted data * @param dataOut Last block of encrypted data
* @param dataOutLength Length 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 chaining Chaining mode
* @param key AES key * @param key AES key
* @param keyLength AES key length * @param keyLength AES key length
@ -286,47 +293,47 @@ namespace gourou
* @param dataOut Encrypted data * @param dataOut Encrypted data
* @param dataOutLength Length of encrypted data * @param dataOutLength Length of encrypted data
*/ */
virtual void AESDecrypt(CHAINING_MODE chaining, virtual void Decrypt(CRYPTO_ALGO algo, CHAINING_MODE chaining,
const unsigned char* key, unsigned int keyLength, const unsigned char* key, unsigned int keyLength,
const unsigned char* iv, unsigned int ivLength, const unsigned char* iv, unsigned int ivLength,
const unsigned char* dataIn, unsigned int dataInLength, const unsigned char* dataIn, unsigned int dataInLength,
unsigned char* dataOut, unsigned int* dataOutLength) = 0; unsigned char* dataOut, unsigned int* dataOutLength) = 0;
/** /**
* @brief Init AES decryption * @brief Init decryption
* *
* @param chaining Chaining mode * @param chaining Chaining mode
* @param key AES key * @param key Key
* @param keyLength AES key length * @param keyLength Key length
* @param iv IV key * @param iv IV key
* @param ivLength IV key length * @param ivLength IV key length
* *
* @return AES handler * @return AES handler
*/ */
virtual void* AESDecryptInit(CHAINING_MODE chaining, virtual void* DecryptInit(CRYPTO_ALGO algo, CHAINING_MODE chaining,
const unsigned char* key, unsigned int keyLength, const unsigned char* key, unsigned int keyLength,
const unsigned char* iv=0, unsigned int ivLength=0) = 0; const unsigned char* iv=0, unsigned int ivLength=0) = 0;
/** /**
* @brief Decrypt data * @brief Decrypt data
* *
* @param handler AES handler * @param handler Crypto handler
* @param dataIn Data to decrypt * @param dataIn Data to decrypt
* @param dataInLength Data length * @param dataInLength Data length
* @param dataOut Decrypted data * @param dataOut Decrypted data
* @param dataOutLength Length of decrypted data * @param dataOutLength Length of decrypted data
*/ */
virtual void AESDecryptUpdate(void* handler, const unsigned char* dataIn, unsigned int dataInLength, virtual void DecryptUpdate(void* handler, const unsigned char* dataIn, unsigned int dataInLength,
unsigned char* dataOut, unsigned int* dataOutLength) = 0; 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 * Destroy handler at the end
* *
* @param handler AES handler * @param handler Crypto handler
* @param dataOut Last block decrypted data * @param dataOut Last block decrypted data
* @param dataOutLength Length of 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;
}; };

View File

@ -47,23 +47,28 @@
/* Digest interface */ /* Digest interface */
void* DRMProcessorClientImpl::createDigest(const std::string& digestName) 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()); 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) 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 DRMProcessorClientImpl::digestFinalize(void* handler, unsigned char* digestOut)
{ {
int res = EVP_DigestFinal((EVP_MD_CTX *)handler, digestOut, NULL); int res = EVP_DigestFinal((EVP_MD_CTX *)handler, digestOut, NULL);
EVP_MD_CTX_free((EVP_MD_CTX *)handler); 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) int DRMProcessorClientImpl::digest(const std::string& digestName, unsigned char* data, unsigned int length, unsigned char* digestOut)
@ -283,33 +288,35 @@ void DRMProcessorClientImpl::extractCertificate(const unsigned char* RSAKey, uns
} }
/* Crypto interface */ /* Crypto interface */
void DRMProcessorClientImpl::AESEncrypt(CHAINING_MODE chaining, void DRMProcessorClientImpl::Encrypt(CRYPTO_ALGO algo, CHAINING_MODE chaining,
const unsigned char* key, unsigned int keyLength, const unsigned char* key, unsigned int keyLength,
const unsigned char* iv, unsigned int ivLength, const unsigned char* iv, unsigned int ivLength,
const unsigned char* dataIn, unsigned int dataInLength, const unsigned char* dataIn, unsigned int dataInLength,
unsigned char* dataOut, unsigned int* dataOutLength) unsigned char* dataOut, unsigned int* dataOutLength)
{ {
void* handler = AESEncryptInit(chaining, key, keyLength, iv, ivLength); void* handler = EncryptInit(algo, chaining, key, keyLength, iv, ivLength);
AESEncryptUpdate(handler, dataIn, dataInLength, dataOut, dataOutLength); EncryptUpdate(handler, dataIn, dataInLength, dataOut, dataOutLength);
AESEncryptFinalize(handler, dataOut+*dataOutLength, 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* key, unsigned int keyLength,
const unsigned char* iv, unsigned int ivLength) const unsigned char* iv, unsigned int ivLength)
{ {
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
if (algo == ALGO_AES)
{
switch(keyLength) switch(keyLength)
{ {
case 16: case 16:
switch(chaining) switch(chaining)
{ {
case CHAIN_ECB: case CHAIN_ECB:
EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, iv); EVP_EncryptInit(ctx, EVP_aes_128_ecb(), key, iv);
break; break;
case CHAIN_CBC: case CHAIN_CBC:
EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv); EVP_EncryptInit(ctx, EVP_aes_128_cbc(), key, iv);
break; break;
default: default:
EXCEPTION(gourou::CLIENT_BAD_CHAINING, "Unknown chaining mode " << chaining); EXCEPTION(gourou::CLIENT_BAD_CHAINING, "Unknown chaining mode " << chaining);
@ -319,26 +326,37 @@ void* DRMProcessorClientImpl::AESEncryptInit(CHAINING_MODE chaining,
EVP_CIPHER_CTX_free(ctx); EVP_CIPHER_CTX_free(ctx);
EXCEPTION(gourou::CLIENT_BAD_KEY_SIZE, "Invalid key size " << keyLength); 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; return ctx;
} }
void* DRMProcessorClientImpl::AESDecryptInit(CHAINING_MODE chaining, void* DRMProcessorClientImpl::DecryptInit(CRYPTO_ALGO algo, CHAINING_MODE chaining,
const unsigned char* key, unsigned int keyLength, const unsigned char* key, unsigned int keyLength,
const unsigned char* iv, unsigned int ivLength) const unsigned char* iv, unsigned int ivLength)
{ {
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
if (algo == ALGO_AES)
{
switch(keyLength) switch(keyLength)
{ {
case 16: case 16:
switch(chaining) switch(chaining)
{ {
case CHAIN_ECB: case CHAIN_ECB:
EVP_DecryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, iv); EVP_DecryptInit(ctx, EVP_aes_128_ecb(), key, iv);
break; break;
case CHAIN_CBC: case CHAIN_CBC:
EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv); EVP_DecryptInit(ctx, EVP_aes_128_cbc(), key, iv);
break; break;
default: default:
EXCEPTION(gourou::CLIENT_BAD_CHAINING, "Unknown chaining mode " << chaining); EXCEPTION(gourou::CLIENT_BAD_CHAINING, "Unknown chaining mode " << chaining);
@ -348,17 +366,27 @@ void* DRMProcessorClientImpl::AESDecryptInit(CHAINING_MODE chaining,
EVP_CIPHER_CTX_free(ctx); EVP_CIPHER_CTX_free(ctx);
EXCEPTION(gourou::CLIENT_BAD_KEY_SIZE, "Invalid key size " << keyLength); 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; return ctx;
} }
void DRMProcessorClientImpl::AESEncryptUpdate(void* handler, const unsigned char* dataIn, unsigned int dataInLength, void DRMProcessorClientImpl::EncryptUpdate(void* handler, const unsigned char* dataIn, unsigned int dataInLength,
unsigned char* dataOut, unsigned int* dataOutLength) unsigned char* dataOut, unsigned int* dataOutLength)
{ {
EVP_EncryptUpdate((EVP_CIPHER_CTX*)handler, dataOut, (int*)dataOutLength, dataIn, dataInLength); EVP_EncryptUpdate((EVP_CIPHER_CTX*)handler, dataOut, (int*)dataOutLength, dataIn, dataInLength);
} }
void DRMProcessorClientImpl::AESEncryptFinalize(void* handler, void DRMProcessorClientImpl::EncryptFinalize(void* handler,
unsigned char* dataOut, unsigned int* dataOutLength) unsigned char* dataOut, unsigned int* dataOutLength)
{ {
int len; int len;
@ -367,24 +395,24 @@ void DRMProcessorClientImpl::AESEncryptFinalize(void* handler,
EVP_CIPHER_CTX_free((EVP_CIPHER_CTX*)handler); EVP_CIPHER_CTX_free((EVP_CIPHER_CTX*)handler);
} }
void DRMProcessorClientImpl::AESDecrypt(CHAINING_MODE chaining, void DRMProcessorClientImpl::Decrypt(CRYPTO_ALGO algo, CHAINING_MODE chaining,
const unsigned char* key, unsigned int keyLength, const unsigned char* key, unsigned int keyLength,
const unsigned char* iv, unsigned int ivLength, const unsigned char* iv, unsigned int ivLength,
const unsigned char* dataIn, unsigned int dataInLength, const unsigned char* dataIn, unsigned int dataInLength,
unsigned char* dataOut, unsigned int* dataOutLength) unsigned char* dataOut, unsigned int* dataOutLength)
{ {
void* handler = AESDecryptInit(chaining, key, keyLength, iv, ivLength); void* handler = DecryptInit(algo, chaining, key, keyLength, iv, ivLength);
AESDecryptUpdate(handler, dataIn, dataInLength, dataOut, dataOutLength); DecryptUpdate(handler, dataIn, dataInLength, dataOut, dataOutLength);
AESDecryptFinalize(handler, dataOut+*dataOutLength, dataOutLength); DecryptFinalize(handler, dataOut+*dataOutLength, dataOutLength);
} }
void DRMProcessorClientImpl::AESDecryptUpdate(void* handler, const unsigned char* dataIn, unsigned int dataInLength, void DRMProcessorClientImpl::DecryptUpdate(void* handler, const unsigned char* dataIn, unsigned int dataInLength,
unsigned char* dataOut, unsigned int* dataOutLength) unsigned char* dataOut, unsigned int* dataOutLength)
{ {
EVP_DecryptUpdate((EVP_CIPHER_CTX*)handler, dataOut, (int*)dataOutLength, dataIn, dataInLength); 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; int len;
EVP_DecryptFinal_ex((EVP_CIPHER_CTX*)handler, dataOut, &len); EVP_DecryptFinal_ex((EVP_CIPHER_CTX*)handler, dataOut, &len);

View File

@ -73,34 +73,34 @@ public:
unsigned char** certOut, unsigned int* certOutLength); unsigned char** certOut, unsigned int* certOutLength);
/* Crypto interface */ /* Crypto interface */
virtual void AESEncrypt(CHAINING_MODE chaining, virtual void Encrypt(CRYPTO_ALGO algo, CHAINING_MODE chaining,
const unsigned char* key, unsigned int keyLength, const unsigned char* key, unsigned int keyLength,
const unsigned char* iv, unsigned int ivLength, const unsigned char* iv, unsigned int ivLength,
const unsigned char* dataIn, unsigned int dataInLength, const unsigned char* dataIn, unsigned int dataInLength,
unsigned char* dataOut, unsigned int* dataOutLength); unsigned char* dataOut, unsigned int* dataOutLength);
virtual void* AESEncryptInit(CHAINING_MODE chaining, virtual void* EncryptInit(CRYPTO_ALGO algo, CHAINING_MODE chaining,
const unsigned char* key, unsigned int keyLength, const unsigned char* key, unsigned int keyLength,
const unsigned char* iv=0, unsigned int ivLength=0); 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); 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, virtual void Decrypt(CRYPTO_ALGO algo, CHAINING_MODE chaining,
const unsigned char* key, unsigned int keyLength, const unsigned char* key, unsigned int keyLength,
const unsigned char* iv, unsigned int ivLength, const unsigned char* iv, unsigned int ivLength,
const unsigned char* dataIn, unsigned int dataInLength, const unsigned char* dataIn, unsigned int dataInLength,
unsigned char* dataOut, unsigned int* dataOutLength); unsigned char* dataOut, unsigned int* dataOutLength);
virtual void* AESDecryptInit(CHAINING_MODE chaining, virtual void* DecryptInit(CRYPTO_ALGO algo, CHAINING_MODE chaining,
const unsigned char* key, unsigned int keyLength, const unsigned char* key, unsigned int keyLength,
const unsigned char* iv=0, unsigned int ivLength=0); const unsigned char* iv=0, unsigned int ivLength=0);
virtual void AESDecryptUpdate(void* handler, const unsigned char* dataIn, unsigned int dataInLength, virtual void DecryptUpdate(void* handler, const unsigned char* dataIn, unsigned int dataInLength,
unsigned char* dataOut, unsigned int* dataOutLength); unsigned char* dataOut, unsigned int* dataOutLength);
virtual void AESDecryptFinalize(void* handler, unsigned char* dataOut, unsigned int* dataOutLength); virtual void DecryptFinalize(void* handler, unsigned char* dataOut, unsigned int* dataOutLength);
/* ZIP Interface */ /* ZIP Interface */
virtual void* zipOpen(const std::string& path); virtual void* zipOpen(const std::string& path);