mirror of
https://github.com/nextcloud/desktop.git
synced 2024-12-13 15:46:01 +03:00
[cse] Update the encrypt and decrypt algorithm to GCM
This commit is contained in:
parent
4f7265c04f
commit
e0d368cbb3
1 changed files with 85 additions and 29 deletions
|
@ -38,40 +38,65 @@ namespace {
|
|||
|
||||
int encrypt(unsigned char *plaintext,
|
||||
int plaintext_len,
|
||||
unsigned char *aad,
|
||||
int aad_len,
|
||||
unsigned char *key,
|
||||
unsigned char *iv,
|
||||
unsigned char *ciphertext)
|
||||
unsigned char *ciphertext,
|
||||
unsigned char *tag)
|
||||
{
|
||||
EVP_CIPHER_CTX *ctx = nullptr;
|
||||
int len = 0;
|
||||
int ciphertext_len = 0;
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
int len;
|
||||
int ciphertext_len;
|
||||
|
||||
/* Create and initialise the context */
|
||||
if(!(ctx = EVP_CIPHER_CTX_new())) {
|
||||
handleErrors();
|
||||
}
|
||||
|
||||
/* Initialise the encryption operation. IMPORTANT - ensure you use a key
|
||||
* and IV size appropriate for your cipher
|
||||
* In this example we are using 256 bit AES (i.e. a 256 bit key). The
|
||||
* IV size for *most* modes is the same as the block size. For AES this
|
||||
* is 128 bits */
|
||||
if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, key, iv)) {
|
||||
/* Initialise the encryption operation. */
|
||||
if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)) {
|
||||
handleErrors();
|
||||
}
|
||||
|
||||
// Figure out if I need to call this multiple times.
|
||||
/* Set IV length if default 12 bytes (96 bits) is not appropriate */
|
||||
if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL)) {
|
||||
handleErrors();
|
||||
}
|
||||
|
||||
/* Initialise key and IV */
|
||||
if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) {
|
||||
handleErrors();
|
||||
}
|
||||
|
||||
/* Provide any AAD data. This can be called zero or more times as
|
||||
* required
|
||||
*/
|
||||
if(1 != EVP_EncryptUpdate(ctx, NULL, &len, aad, aad_len)) {
|
||||
handleErrors();
|
||||
}
|
||||
|
||||
/* Provide the message to be encrypted, and obtain the encrypted output.
|
||||
* EVP_EncryptUpdate can be called multiple times if necessary
|
||||
*/
|
||||
if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) {
|
||||
handleErrors();
|
||||
}
|
||||
ciphertext_len = len;
|
||||
|
||||
// Finalize Encryption
|
||||
/* Finalise the encryption. Normally ciphertext bytes may be written at
|
||||
* this stage, but this does not occur in GCM mode
|
||||
*/
|
||||
if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) {
|
||||
handleErrors();
|
||||
}
|
||||
ciphertext_len += len;
|
||||
|
||||
/* Get the tag */
|
||||
if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag)) {
|
||||
handleErrors();
|
||||
}
|
||||
|
||||
/* Clean up */
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
|
||||
|
@ -80,46 +105,77 @@ namespace {
|
|||
|
||||
int decrypt(unsigned char *ciphertext,
|
||||
int ciphertext_len,
|
||||
unsigned char *aad,
|
||||
int aad_len,
|
||||
unsigned char *tag,
|
||||
unsigned char *key,
|
||||
unsigned char *iv,
|
||||
unsigned char *plaintext)
|
||||
{
|
||||
EVP_CIPHER_CTX *ctx = nullptr;
|
||||
|
||||
int len = 0;
|
||||
|
||||
int plaintext_len = 0;
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
int len;
|
||||
int plaintext_len;
|
||||
int ret;
|
||||
|
||||
/* Create and initialise the context */
|
||||
if(!(ctx = EVP_CIPHER_CTX_new())) {
|
||||
handleErrors();
|
||||
}
|
||||
|
||||
/* Initialise the decryption operation. IMPORTANT - ensure you use a key
|
||||
* and IV size appropriate for your cipher
|
||||
* In this example we are using 256 bit AES (i.e. a 256 bit key). The
|
||||
* IV size for *most* modes is the same as the block size. For AES this
|
||||
* is 128 bits */
|
||||
if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, key, iv)) {
|
||||
/* Initialise the decryption operation. */
|
||||
if(!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)) {
|
||||
handleErrors();
|
||||
}
|
||||
|
||||
// Verify if we need to call this more than one time
|
||||
if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len)) {
|
||||
/* Set IV length. Not necessary if this is 12 bytes (96 bits) */
|
||||
if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL)) {
|
||||
handleErrors();
|
||||
}
|
||||
|
||||
/* Initialise key and IV */
|
||||
if(!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) {
|
||||
handleErrors();
|
||||
}
|
||||
|
||||
/* Provide any AAD data. This can be called zero or more times as
|
||||
* required
|
||||
*/
|
||||
if(!EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_len)) {
|
||||
handleErrors();
|
||||
}
|
||||
|
||||
/* Provide the message to be decrypted, and obtain the plaintext output.
|
||||
* EVP_DecryptUpdate can be called multiple times if necessary
|
||||
*/
|
||||
if(!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len)) {
|
||||
handleErrors();
|
||||
}
|
||||
plaintext_len = len;
|
||||
|
||||
// Finalize Decrypt
|
||||
if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) {
|
||||
/* Set expected tag value. Works in OpenSSL 1.0.1d and later */
|
||||
if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tag)) {
|
||||
handleErrors();
|
||||
}
|
||||
plaintext_len += len;
|
||||
|
||||
/* Finalise the decryption. A positive return value indicates success,
|
||||
* anything else is a failure - the plaintext is not trustworthy.
|
||||
*/
|
||||
ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len);
|
||||
|
||||
/* Clean up */
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
|
||||
return plaintext_len;
|
||||
if(ret > 0)
|
||||
{
|
||||
/* Success */
|
||||
plaintext_len += len;
|
||||
return plaintext_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Verify failed */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue