mirror of
https://github.com/OpenVPN/openvpn3.git
synced 2024-09-20 04:02:15 +02:00
Assume AEAD tag at the end of input if not given seperately
Signed-off-by: Arne Schwabe <arne@openvpn.net>
This commit is contained in:
parent
880ebb081a
commit
d52d98c7ec
@ -123,7 +123,20 @@ class CipherContextAEAD : public CipherContextCommon
|
|||||||
OPENVPN_THROW(mbedtls_aead_error, "mbedtls_cipher_auth_encrypt failed with status=" << status);
|
OPENVPN_THROW(mbedtls_aead_error, "mbedtls_cipher_auth_encrypt failed with status=" << status);
|
||||||
}
|
}
|
||||||
|
|
||||||
// input and output may NOT be equal
|
/**
|
||||||
|
* Decrypts AEAD encrypted data. Note that this method ignores the tag parameter
|
||||||
|
* and the tag is assumed to be part of input and at the end of the input.
|
||||||
|
*
|
||||||
|
* @param input Input data to decrypt
|
||||||
|
* @param output Where decrypted data will be written to
|
||||||
|
* @param iv IV of the encrypted data.
|
||||||
|
* @param length length the of the data, this includes the tag at the end.
|
||||||
|
* @param ad start of the additional data
|
||||||
|
* @param ad_len length of the additional data
|
||||||
|
* @param tag ignored by the mbed TLS variant of the method. (see OpenSSL variant of the method for more details).
|
||||||
|
*
|
||||||
|
* input and output may NOT be equal
|
||||||
|
*/
|
||||||
bool decrypt(const unsigned char *input,
|
bool decrypt(const unsigned char *input,
|
||||||
unsigned char *output,
|
unsigned char *output,
|
||||||
size_t length,
|
size_t length,
|
||||||
@ -134,6 +147,12 @@ class CipherContextAEAD : public CipherContextCommon
|
|||||||
{
|
{
|
||||||
check_initialized();
|
check_initialized();
|
||||||
|
|
||||||
|
if (unlikely(tag != nullptr))
|
||||||
|
{
|
||||||
|
/* If we are called with a non-null tag, the function is not going to be able to decrypt */
|
||||||
|
throw mbedtls_aead_error("tag must be null for aead decrypt");
|
||||||
|
}
|
||||||
|
|
||||||
size_t olen;
|
size_t olen;
|
||||||
const int status = mbedtls_cipher_auth_decrypt_ext(&ctx,
|
const int status = mbedtls_cipher_auth_decrypt_ext(&ctx,
|
||||||
iv,
|
iv,
|
||||||
|
@ -63,7 +63,7 @@ class CipherContextAEAD
|
|||||||
};
|
};
|
||||||
|
|
||||||
// OpenSSL cipher constants
|
// OpenSSL cipher constants
|
||||||
enum
|
enum : size_t
|
||||||
{
|
{
|
||||||
IV_LEN = 12,
|
IV_LEN = 12,
|
||||||
AUTH_TAG_LEN = 16
|
AUTH_TAG_LEN = 16
|
||||||
@ -172,16 +172,38 @@ class CipherContextAEAD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrypts AEAD encrypted data. Note that if tag is the nullptr the tag is assumed to be
|
||||||
|
* part of input and at the end of the input. The length parameter of input includes the tag in
|
||||||
|
* this case
|
||||||
|
*
|
||||||
|
* @param input Input data to decrypt
|
||||||
|
* @param output Where decrypted data will be written to
|
||||||
|
* @param iv IV of the encrypted data.
|
||||||
|
* @param length length the of the data, this includes the tag at the end if tag is not a nullptr.
|
||||||
|
* @param ad start of the additional data
|
||||||
|
* @param ad_len length of the additional data
|
||||||
|
* @param tag location of the tag to use or nullptr if at the end of the input
|
||||||
|
*/
|
||||||
bool decrypt(const unsigned char *input,
|
bool decrypt(const unsigned char *input,
|
||||||
unsigned char *output,
|
unsigned char *output,
|
||||||
size_t length,
|
size_t length,
|
||||||
const unsigned char *iv,
|
const unsigned char *iv,
|
||||||
unsigned char *tag,
|
const unsigned char *tag,
|
||||||
const unsigned char *ad,
|
const unsigned char *ad,
|
||||||
size_t ad_len)
|
size_t ad_len)
|
||||||
{
|
{
|
||||||
int len;
|
if (!tag)
|
||||||
int plaintext_len;
|
{
|
||||||
|
/* Tag is at the end of input, check that input is large enough to hold the tag */
|
||||||
|
if (length < AUTH_TAG_LEN)
|
||||||
|
{
|
||||||
|
throw openssl_gcm_error("decrypt input length too short");
|
||||||
|
}
|
||||||
|
|
||||||
|
length = length - AUTH_TAG_LEN;
|
||||||
|
tag = input + length;
|
||||||
|
}
|
||||||
|
|
||||||
check_initialized();
|
check_initialized();
|
||||||
if (!EVP_DecryptInit_ex(ctx, nullptr, nullptr, nullptr, iv))
|
if (!EVP_DecryptInit_ex(ctx, nullptr, nullptr, nullptr, iv))
|
||||||
@ -189,6 +211,8 @@ class CipherContextAEAD
|
|||||||
openssl_clear_error_stack();
|
openssl_clear_error_stack();
|
||||||
throw openssl_gcm_error("EVP_DecryptInit_ex (reset)");
|
throw openssl_gcm_error("EVP_DecryptInit_ex (reset)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int len;
|
||||||
if (!EVP_DecryptUpdate(ctx, nullptr, &len, ad, int(ad_len)))
|
if (!EVP_DecryptUpdate(ctx, nullptr, &len, ad, int(ad_len)))
|
||||||
{
|
{
|
||||||
openssl_clear_error_stack();
|
openssl_clear_error_stack();
|
||||||
@ -199,8 +223,11 @@ class CipherContextAEAD
|
|||||||
openssl_clear_error_stack();
|
openssl_clear_error_stack();
|
||||||
throw openssl_gcm_error("EVP_DecryptUpdate data");
|
throw openssl_gcm_error("EVP_DecryptUpdate data");
|
||||||
}
|
}
|
||||||
plaintext_len = len;
|
|
||||||
if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, AUTH_TAG_LEN, tag))
|
int plaintext_len = len;
|
||||||
|
/** This API of OpenSSL does not modify the tag it is given but the function signature always expects
|
||||||
|
* a modifiable tag, so we have to const cast it to get around this restriction */
|
||||||
|
if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, AUTH_TAG_LEN, const_cast<unsigned char *>(tag)))
|
||||||
{
|
{
|
||||||
openssl_clear_error_stack();
|
openssl_clear_error_stack();
|
||||||
throw openssl_gcm_error("EVP_CIPHER_CTX_ctrl set tag");
|
throw openssl_gcm_error("EVP_CIPHER_CTX_ctrl set tag");
|
||||||
|
Loading…
Reference in New Issue
Block a user