mirror of
https://github.com/moonlight-stream/moonlight-common-c.git
synced 2025-08-18 09:25:49 +00:00
Optimize OpenSSL backend to avoid redundant reinitialization
It is best to pass as few parameters to EVP_*Init_ex() as possible. Passing a key, IV, or cipher will cause redundant work to happen behind the scenes as OpenSSL doesn't check whether they have actually changed. This avoids a malloc()/free() and redoing AES key expansion for every message that is encrypted and decrypted.
This commit is contained in:
parent
29d2cc6d5b
commit
8354c403f4
@ -24,6 +24,9 @@ static int addPkcs7PaddingInPlace(unsigned char* plaintext, int plaintextLen) {
|
|||||||
// When CIPHER_FLAG_PAD_TO_BLOCK_SIZE is used, inputData buffer must be allocated such that
|
// When CIPHER_FLAG_PAD_TO_BLOCK_SIZE is used, inputData buffer must be allocated such that
|
||||||
// the buffer length is at least ROUND_TO_PKCS7_PADDED_LEN(inputDataLength) and inputData
|
// the buffer length is at least ROUND_TO_PKCS7_PADDED_LEN(inputDataLength) and inputData
|
||||||
// buffer may be modified!
|
// buffer may be modified!
|
||||||
|
// For GCM, the IV can change from message to message without CIPHER_FLAG_RESET_IV.
|
||||||
|
// CIPHER_FLAG_RESET_IV is only required for GCM when the IV length changes.
|
||||||
|
// Changing the key between encrypt/decrypt calls on a single context is not supported.
|
||||||
bool PltEncryptMessage(PPLT_CRYPTO_CONTEXT ctx, int algorithm, int flags,
|
bool PltEncryptMessage(PPLT_CRYPTO_CONTEXT ctx, int algorithm, int flags,
|
||||||
unsigned char* key, int keyLength,
|
unsigned char* key, int keyLength,
|
||||||
unsigned char* iv, int ivLength,
|
unsigned char* iv, int ivLength,
|
||||||
@ -121,26 +124,47 @@ bool PltEncryptMessage(PPLT_CRYPTO_CONTEXT ctx, int algorithm, int flags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (algorithm == ALGORITHM_AES_GCM) {
|
if (algorithm == ALGORITHM_AES_GCM) {
|
||||||
if (EVP_EncryptInit_ex(ctx->ctx, cipher, NULL, NULL, NULL) != 1) {
|
if (!ctx->initialized || (flags & CIPHER_FLAG_RESET_IV)) {
|
||||||
return false;
|
// Perform a full initialization. This codepath also allows
|
||||||
}
|
// us to change the IV length if required.
|
||||||
|
if (EVP_EncryptInit_ex(ctx->ctx, cipher, NULL, NULL, NULL) != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (EVP_CIPHER_CTX_ctrl(ctx->ctx, EVP_CTRL_GCM_SET_IVLEN, ivLength, NULL) != 1) {
|
if (EVP_CIPHER_CTX_ctrl(ctx->ctx, EVP_CTRL_GCM_SET_IVLEN, ivLength, NULL) != 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EVP_EncryptInit_ex(ctx->ctx, NULL, NULL, key, iv) != 1) {
|
if (EVP_EncryptInit_ex(ctx->ctx, NULL, NULL, key, iv) != 1) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->initialized = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Calling with cipher == NULL results in a parameter change
|
||||||
|
// without requiring a reallocation of the internal cipher ctx.
|
||||||
|
if (EVP_EncryptInit_ex(ctx->ctx, NULL, NULL, NULL, iv) != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!ctx->initialized || (flags & CIPHER_FLAG_RESET_IV)) {
|
if (!ctx->initialized) {
|
||||||
|
// Perform a full initialization
|
||||||
if (EVP_EncryptInit_ex(ctx->ctx, cipher, NULL, key, iv) != 1) {
|
if (EVP_EncryptInit_ex(ctx->ctx, cipher, NULL, key, iv) != 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->initialized = true;
|
ctx->initialized = true;
|
||||||
}
|
}
|
||||||
|
else if (flags & CIPHER_FLAG_RESET_IV) {
|
||||||
|
// Calling with cipher == NULL results in a parameter change
|
||||||
|
// without requiring a reallocation of the internal cipher ctx.
|
||||||
|
if (EVP_EncryptInit_ex(ctx->ctx, NULL, NULL, NULL, iv) != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (flags & CIPHER_FLAG_PAD_TO_BLOCK_SIZE) {
|
if (flags & CIPHER_FLAG_PAD_TO_BLOCK_SIZE) {
|
||||||
inputDataLength = addPkcs7PaddingInPlace(inputData, inputDataLength);
|
inputDataLength = addPkcs7PaddingInPlace(inputData, inputDataLength);
|
||||||
@ -180,6 +204,9 @@ bool PltEncryptMessage(PPLT_CRYPTO_CONTEXT ctx, int algorithm, int flags,
|
|||||||
|
|
||||||
// When CBC is used, outputData buffer must be allocated such that the buffer length is
|
// When CBC is used, outputData buffer must be allocated such that the buffer length is
|
||||||
// at least ROUND_TO_PKCS7_PADDED_LEN(inputDataLength) to allow room for PKCS7 padding.
|
// at least ROUND_TO_PKCS7_PADDED_LEN(inputDataLength) to allow room for PKCS7 padding.
|
||||||
|
// For GCM, the IV can change from message to message without CIPHER_FLAG_RESET_IV.
|
||||||
|
// CIPHER_FLAG_RESET_IV is only required for GCM when the IV length changes.
|
||||||
|
// Changing the key between encrypt/decrypt calls on a single context is not supported.
|
||||||
bool PltDecryptMessage(PPLT_CRYPTO_CONTEXT ctx, int algorithm, int flags,
|
bool PltDecryptMessage(PPLT_CRYPTO_CONTEXT ctx, int algorithm, int flags,
|
||||||
unsigned char* key, int keyLength,
|
unsigned char* key, int keyLength,
|
||||||
unsigned char* iv, int ivLength,
|
unsigned char* iv, int ivLength,
|
||||||
@ -273,26 +300,47 @@ bool PltDecryptMessage(PPLT_CRYPTO_CONTEXT ctx, int algorithm, int flags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (algorithm == ALGORITHM_AES_GCM) {
|
if (algorithm == ALGORITHM_AES_GCM) {
|
||||||
if (EVP_DecryptInit_ex(ctx->ctx, cipher, NULL, NULL, NULL) != 1) {
|
if (!ctx->initialized || (flags & CIPHER_FLAG_RESET_IV)) {
|
||||||
return false;
|
// Perform a full initialization. This codepath also allows
|
||||||
}
|
// us to change the IV length if required.
|
||||||
|
if (EVP_DecryptInit_ex(ctx->ctx, cipher, NULL, NULL, NULL) != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (EVP_CIPHER_CTX_ctrl(ctx->ctx, EVP_CTRL_GCM_SET_IVLEN, ivLength, NULL) != 1) {
|
if (EVP_CIPHER_CTX_ctrl(ctx->ctx, EVP_CTRL_GCM_SET_IVLEN, ivLength, NULL) != 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EVP_DecryptInit_ex(ctx->ctx, NULL, NULL, key, iv) != 1) {
|
if (EVP_DecryptInit_ex(ctx->ctx, NULL, NULL, key, iv) != 1) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->initialized = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Calling with cipher == NULL results in a parameter change
|
||||||
|
// without requiring a reallocation of the internal cipher ctx.
|
||||||
|
if (EVP_DecryptInit_ex(ctx->ctx, NULL, NULL, NULL, iv) != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!ctx->initialized || (flags & CIPHER_FLAG_RESET_IV)) {
|
if (!ctx->initialized) {
|
||||||
|
// Perform a full initialization
|
||||||
if (EVP_DecryptInit_ex(ctx->ctx, cipher, NULL, key, iv) != 1) {
|
if (EVP_DecryptInit_ex(ctx->ctx, cipher, NULL, key, iv) != 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->initialized = true;
|
ctx->initialized = true;
|
||||||
}
|
}
|
||||||
|
else if (flags & CIPHER_FLAG_RESET_IV) {
|
||||||
|
// Calling with cipher == NULL results in a parameter change
|
||||||
|
// without requiring a reallocation of the internal cipher ctx.
|
||||||
|
if (EVP_DecryptInit_ex(ctx->ctx, NULL, NULL, NULL, iv) != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EVP_DecryptUpdate(ctx->ctx, outputData, outputDataLength, inputData, inputDataLength) != 1) {
|
if (EVP_DecryptUpdate(ctx->ctx, outputData, outputDataLength, inputData, inputDataLength) != 1) {
|
||||||
|
@ -14,7 +14,7 @@ typedef struct _PLT_CRYPTO_CONTEXT {
|
|||||||
bool initialized;
|
bool initialized;
|
||||||
mbedtls_cipher_context_t ctx;
|
mbedtls_cipher_context_t ctx;
|
||||||
#else
|
#else
|
||||||
bool initialized; // Used for CBC only
|
bool initialized;
|
||||||
EVP_CIPHER_CTX* ctx;
|
EVP_CIPHER_CTX* ctx;
|
||||||
#endif
|
#endif
|
||||||
} PLT_CRYPTO_CONTEXT, *PPLT_CRYPTO_CONTEXT;
|
} PLT_CRYPTO_CONTEXT, *PPLT_CRYPTO_CONTEXT;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user