diff --git a/src/Mayaqua/Encrypt.c b/src/Mayaqua/Encrypt.c index 9d2c1a0d..b59ff886 100644 --- a/src/Mayaqua/Encrypt.c +++ b/src/Mayaqua/Encrypt.c @@ -570,6 +570,7 @@ CIPHER *NewCipher(char *name) EVP_CIPHER_CTX_init(c->Ctx); #endif + c->IsAeadCipher = EVP_CIPHER_flags(c->Cipher) & EVP_CIPH_FLAG_AEAD_CIPHER; c->BlockSize = EVP_CIPHER_block_size(c->Cipher); c->KeySize = EVP_CIPHER_key_length(c->Cipher); c->IvSize = EVP_CIPHER_iv_length(c->Cipher); @@ -634,6 +635,74 @@ UINT CipherProcess(CIPHER *c, void *iv, void *dest, void *src, UINT size) return r + r2; } +// Process encryption / decryption (AEAD) +UINT CipherProcessAead(CIPHER *c, void *iv, void *tag, UINT tag_size, void *dest, void *src, UINT src_size, void *aad, UINT aad_size) +{ + int r = src_size; + int r2 = 0; + // Validate arguments + if (c == NULL) + { + return 0; + } + else if (c->IsNullCipher) + { + Copy(dest, src, src_size); + return src_size; + } + else if (c->IsAeadCipher == false || iv == NULL || tag == NULL || tag_size == 0 || dest == NULL || src == NULL || src_size == 0) + { + return 0; + } + + if (EVP_CipherInit_ex(c->Ctx, NULL, NULL, NULL, iv, c->Encrypt) == false) + { + Debug("CipherProcessAead(): EVP_CipherInit_ex() failed with error: %s\n", OpenSSL_Error()); + return 0; + } + + if (c->Encrypt == false) + { + if (EVP_CIPHER_CTX_ctrl(c->Ctx, EVP_CTRL_AEAD_SET_TAG, tag_size, tag) == false) + { + Debug("CipherProcessAead(): EVP_CIPHER_CTX_ctrl() failed to set the tag!\n"); + return 0; + } + } + + if (aad != NULL && aad_size != 0) + { + if (EVP_CipherUpdate(c->Ctx, NULL, &r, aad, aad_size) == false) + { + Debug("CipherProcessAead(): EVP_CipherUpdate() failed with error: %s\n", OpenSSL_Error()); + return 0; + } + } + + if (EVP_CipherUpdate(c->Ctx, dest, &r, src, src_size) == false) + { + Debug("CipherProcessAead(): EVP_CipherUpdate() failed with error: %s\n", OpenSSL_Error()); + return 0; + } + + if (EVP_CipherFinal_ex(c->Ctx, ((UCHAR *)dest) + (UINT)r, &r2) == false) + { + Debug("CipherProcessAead(): EVP_CipherFinal_ex() failed with error: %s\n", OpenSSL_Error()); + return 0; + } + + if (c->Encrypt) + { + if (EVP_CIPHER_CTX_ctrl(c->Ctx, EVP_CTRL_AEAD_GET_TAG, tag_size, tag) == false) + { + Debug("CipherProcessAead(): EVP_CIPHER_CTX_ctrl() failed to get the tag!\n"); + return 0; + } + } + + return r + r2; +} + // Release of the cipher object void FreeCipher(CIPHER *c) { diff --git a/src/Mayaqua/Encrypt.h b/src/Mayaqua/Encrypt.h index 1b2c0ff9..1a9bb468 100644 --- a/src/Mayaqua/Encrypt.h +++ b/src/Mayaqua/Encrypt.h @@ -239,6 +239,8 @@ void RAND_Free_For_SoftEther(); // OpenSSL <1.1 Shims #if OPENSSL_VERSION_NUMBER < 0x10100000L +# define EVP_CTRL_AEAD_GET_TAG EVP_CTRL_GCM_GET_TAG +# define EVP_CTRL_AEAD_SET_TAG EVP_CTRL_GCM_SET_TAG # define EVP_PKEY_get0_RSA(obj) ((obj)->pkey.rsa) # define EVP_PKEY_base_id(pkey) ((pkey)->type) # define X509_get0_notBefore(x509) ((x509)->cert_info->validity->notBefore) @@ -348,7 +350,7 @@ struct DH_CTX struct CIPHER { char Name[MAX_PATH]; - bool IsNullCipher; + bool IsNullCipher, IsAeadCipher; const struct evp_cipher_st *Cipher; struct evp_cipher_ctx_st *Ctx; bool Encrypt; @@ -523,6 +525,7 @@ CIPHER *NewCipher(char *name); void FreeCipher(CIPHER *c); void SetCipherKey(CIPHER *c, void *key, bool enc); UINT CipherProcess(CIPHER *c, void *iv, void *dest, void *src, UINT size); +UINT CipherProcessAead(CIPHER *c, void *iv, void *tag, UINT tag_size, void *dest, void *src, UINT src_size, void *aad, UINT aad_size); // Hashing MD *NewMd(char *name);