|
|
@@ -67,7 +67,7 @@ namespace {
|
|
|
const char e2e_private[] = "_e2e-private";
|
|
|
const char e2e_mnemonic[] = "_e2e-mnemonic";
|
|
|
|
|
|
- const int blockSize = 1024;
|
|
|
+ constexpr qint64 blockSize = 1024;
|
|
|
|
|
|
QList<QByteArray> oldCipherFormatSplit(const QByteArray &cipher)
|
|
|
{
|
|
|
@@ -298,7 +298,7 @@ namespace {
|
|
|
};
|
|
|
|
|
|
QByteArray BIO2ByteArray(Bio &b) {
|
|
|
- int pending = static_cast<int>(BIO_ctrl_pending(b));
|
|
|
+ int pending = BIO_ctrl_pending(b);
|
|
|
QByteArray res(pending, '\0');
|
|
|
BIO_read(b, unsignedData(res), pending);
|
|
|
return res;
|
|
|
@@ -426,17 +426,17 @@ QByteArray encryptPrivateKey(
|
|
|
}
|
|
|
clen += len;
|
|
|
|
|
|
- /* Get the tag */
|
|
|
- QByteArray tag(OCC::CommonConstants::e2EeTagSize, '\0');
|
|
|
- if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, OCC::CommonConstants::e2EeTagSize, unsignedData(tag))) {
|
|
|
- qCInfo(lcCse()) << "Error getting the tag";
|
|
|
+ /* Get the e2EeTag */
|
|
|
+ QByteArray e2EeTag(OCC::Constants::e2EeTagSize, '\0');
|
|
|
+ if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, OCC::Constants::e2EeTagSize, unsignedData(e2EeTag))) {
|
|
|
+ qCInfo(lcCse()) << "Error getting the e2EeTag";
|
|
|
handleErrors();
|
|
|
}
|
|
|
|
|
|
QByteArray cipherTXT;
|
|
|
- cipherTXT.reserve(clen + 16);
|
|
|
+ cipherTXT.reserve(clen + OCC::Constants::e2EeTagSize);
|
|
|
cipherTXT.append(ctext, clen);
|
|
|
- cipherTXT.append(tag);
|
|
|
+ cipherTXT.append(e2EeTag);
|
|
|
|
|
|
QByteArray result = cipherTXT.toBase64();
|
|
|
result += '|';
|
|
|
@@ -466,8 +466,8 @@ QByteArray decryptPrivateKey(const QByteArray& key, const QByteArray& data) {
|
|
|
QByteArray cipherTXT = QByteArray::fromBase64(cipherTXT64);
|
|
|
QByteArray iv = QByteArray::fromBase64(ivB64);
|
|
|
|
|
|
- QByteArray tag = cipherTXT.right(OCC::CommonConstants::e2EeTagSize);
|
|
|
- cipherTXT.chop(OCC::CommonConstants::e2EeTagSize);
|
|
|
+ const QByteArray e2EeTag = cipherTXT.right(OCC::Constants::e2EeTagSize);
|
|
|
+ cipherTXT.chop(OCC::Constants::e2EeTagSize);
|
|
|
|
|
|
// Init
|
|
|
CipherCtx ctx;
|
|
|
@@ -496,7 +496,7 @@ QByteArray decryptPrivateKey(const QByteArray& key, const QByteArray& data) {
|
|
|
return QByteArray();
|
|
|
}
|
|
|
|
|
|
- QByteArray ptext(cipherTXT.size() + OCC::CommonConstants::e2EeTagSize, '\0');
|
|
|
+ QByteArray ptext(cipherTXT.size() + OCC::Constants::e2EeTagSize, '\0');
|
|
|
int plen = 0;
|
|
|
|
|
|
/* Provide the message to be decrypted, and obtain the plaintext output.
|
|
|
@@ -507,9 +507,9 @@ QByteArray decryptPrivateKey(const QByteArray& key, const QByteArray& data) {
|
|
|
return QByteArray();
|
|
|
}
|
|
|
|
|
|
- /* Set expected tag value. Works in OpenSSL 1.0.1d and later */
|
|
|
- if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, tag.size(), (unsigned char *)tag.constData())) {
|
|
|
- qCInfo(lcCse()) << "Could not set tag";
|
|
|
+ /* Set expected e2EeTag value. Works in OpenSSL 1.0.1d and later */
|
|
|
+ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, e2EeTag.size(), (unsigned char *)e2EeTag.constData())) {
|
|
|
+ qCInfo(lcCse()) << "Could not set e2EeTag";
|
|
|
return QByteArray();
|
|
|
}
|
|
|
|
|
|
@@ -556,8 +556,8 @@ QByteArray decryptStringSymmetric(const QByteArray& key, const QByteArray& data)
|
|
|
QByteArray cipherTXT = QByteArray::fromBase64(cipherTXT64);
|
|
|
QByteArray iv = QByteArray::fromBase64(ivB64);
|
|
|
|
|
|
- QByteArray tag = cipherTXT.right(OCC::CommonConstants::e2EeTagSize);
|
|
|
- cipherTXT.chop(OCC::CommonConstants::e2EeTagSize);
|
|
|
+ const QByteArray e2EeTag = cipherTXT.right(OCC::Constants::e2EeTagSize);
|
|
|
+ cipherTXT.chop(OCC::Constants::e2EeTagSize);
|
|
|
|
|
|
// Init
|
|
|
CipherCtx ctx;
|
|
|
@@ -586,7 +586,7 @@ QByteArray decryptStringSymmetric(const QByteArray& key, const QByteArray& data)
|
|
|
return QByteArray();
|
|
|
}
|
|
|
|
|
|
- QByteArray ptext(cipherTXT.size() + OCC::CommonConstants::e2EeTagSize, '\0');
|
|
|
+ QByteArray ptext(cipherTXT.size() + OCC::Constants::e2EeTagSize, '\0');
|
|
|
int plen = 0;
|
|
|
|
|
|
/* Provide the message to be decrypted, and obtain the plaintext output.
|
|
|
@@ -597,9 +597,9 @@ QByteArray decryptStringSymmetric(const QByteArray& key, const QByteArray& data)
|
|
|
return QByteArray();
|
|
|
}
|
|
|
|
|
|
- /* Set expected tag value. Works in OpenSSL 1.0.1d and later */
|
|
|
- if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, tag.size(), (unsigned char *)tag.constData())) {
|
|
|
- qCInfo(lcCse()) << "Could not set tag";
|
|
|
+ /* Set expected e2EeTag value. Works in OpenSSL 1.0.1d and later */
|
|
|
+ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, e2EeTag.size(), (unsigned char *)e2EeTag.constData())) {
|
|
|
+ qCInfo(lcCse()) << "Could not set e2EeTag";
|
|
|
return QByteArray();
|
|
|
}
|
|
|
|
|
|
@@ -689,18 +689,18 @@ QByteArray encryptStringSymmetric(const QByteArray& key, const QByteArray& data)
|
|
|
}
|
|
|
clen += len;
|
|
|
|
|
|
- /* Get the tag */
|
|
|
- QByteArray tag(OCC::CommonConstants::e2EeTagSize, '\0');
|
|
|
- if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, OCC::CommonConstants::e2EeTagSize, unsignedData(tag))) {
|
|
|
- qCInfo(lcCse()) << "Error getting the tag";
|
|
|
+ /* Get the e2EeTag */
|
|
|
+ QByteArray e2EeTag(OCC::Constants::e2EeTagSize, '\0');
|
|
|
+ if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, OCC::Constants::e2EeTagSize, unsignedData(e2EeTag))) {
|
|
|
+ qCInfo(lcCse()) << "Error getting the e2EeTag";
|
|
|
handleErrors();
|
|
|
return {};
|
|
|
}
|
|
|
|
|
|
QByteArray cipherTXT;
|
|
|
- cipherTXT.reserve(clen + 16);
|
|
|
+ cipherTXT.reserve(clen + OCC::Constants::e2EeTagSize);
|
|
|
cipherTXT.append(ctext, clen);
|
|
|
- cipherTXT.append(tag);
|
|
|
+ cipherTXT.append(e2EeTag);
|
|
|
|
|
|
QByteArray result = cipherTXT.toBase64();
|
|
|
result += '|';
|
|
|
@@ -1653,13 +1653,13 @@ bool EncryptionHelper::fileEncryption(const QByteArray &key, const QByteArray &i
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- QByteArray out(blockSize + OCC::CommonConstants::e2EeTagSize - 1, '\0');
|
|
|
+ QByteArray out(blockSize + OCC::Constants::e2EeTagSize - 1, '\0');
|
|
|
int len = 0;
|
|
|
int total_len = 0;
|
|
|
|
|
|
qCDebug(lcCse) << "Starting to encrypt the file" << input->fileName() << input->atEnd();
|
|
|
while(!input->atEnd()) {
|
|
|
- QByteArray data = input->read(blockSize);
|
|
|
+ const auto data = input->read(blockSize);
|
|
|
|
|
|
if (data.size() == 0) {
|
|
|
qCInfo(lcCse()) << "Could not read data from file";
|
|
|
@@ -1683,15 +1683,15 @@ bool EncryptionHelper::fileEncryption(const QByteArray &key, const QByteArray &i
|
|
|
output->write(out, len);
|
|
|
total_len += len;
|
|
|
|
|
|
- /* Get the tag */
|
|
|
- QByteArray tag(OCC::CommonConstants::e2EeTagSize, '\0');
|
|
|
- if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, OCC::CommonConstants::e2EeTagSize, unsignedData(tag))) {
|
|
|
- qCInfo(lcCse()) << "Could not get tag";
|
|
|
+ /* Get the e2EeTag */
|
|
|
+ QByteArray e2EeTag(OCC::Constants::e2EeTagSize, '\0');
|
|
|
+ if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, OCC::Constants::e2EeTagSize, unsignedData(e2EeTag))) {
|
|
|
+ qCInfo(lcCse()) << "Could not get e2EeTag";
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- returnTag = tag;
|
|
|
- output->write(tag, OCC::CommonConstants::e2EeTagSize);
|
|
|
+ returnTag = e2EeTag;
|
|
|
+ output->write(e2EeTag, OCC::Constants::e2EeTagSize);
|
|
|
|
|
|
input->close();
|
|
|
output->close();
|
|
|
@@ -1734,9 +1734,9 @@ bool EncryptionHelper::fileDecryption(const QByteArray &key, const QByteArray& i
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- qint64 size = input->size() - OCC::CommonConstants::e2EeTagSize;
|
|
|
+ qint64 size = input->size() - OCC::Constants::e2EeTagSize;
|
|
|
|
|
|
- QByteArray out(blockSize + OCC::CommonConstants::e2EeTagSize - 1, '\0');
|
|
|
+ QByteArray out(blockSize + OCC::Constants::e2EeTagSize - 1, '\0');
|
|
|
int len = 0;
|
|
|
|
|
|
while(input->pos() < size) {
|
|
|
@@ -1761,11 +1761,11 @@ bool EncryptionHelper::fileDecryption(const QByteArray &key, const QByteArray& i
|
|
|
output->write(out, len);
|
|
|
}
|
|
|
|
|
|
- QByteArray tag = input->read(OCC::CommonConstants::e2EeTagSize);
|
|
|
+ const QByteArray e2EeTag = input->read(OCC::Constants::e2EeTagSize);
|
|
|
|
|
|
- /* Set expected tag value. Works in OpenSSL 1.0.1d and later */
|
|
|
- if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, tag.size(), (unsigned char *)tag.constData())) {
|
|
|
- qCInfo(lcCse()) << "Could not set expected tag";
|
|
|
+ /* Set expected e2EeTag value. Works in OpenSSL 1.0.1d and later */
|
|
|
+ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, e2EeTag.size(), (unsigned char *)e2EeTag.constData())) {
|
|
|
+ qCInfo(lcCse()) << "Could not set expected e2EeTag";
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
@@ -1807,30 +1807,34 @@ EncryptionHelper::StreamingDecryptor::StreamingDecryptor(const QByteArray &key,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-qint32 EncryptionHelper::StreamingDecryptor::chunkDecryption(const char *input, QIODevice *output, quint32 chunkSize)
|
|
|
+QByteArray EncryptionHelper::StreamingDecryptor::chunkDecryption(const char *input, quint64 chunkSize)
|
|
|
{
|
|
|
+ QByteArray byteArray;
|
|
|
+ QBuffer buffer(&byteArray);
|
|
|
+ buffer.open(QIODevice::WriteOnly);
|
|
|
+
|
|
|
Q_ASSERT(isInitialized());
|
|
|
if (!isInitialized()) {
|
|
|
qCritical(lcCse()) << "Decryption failed. Decryptor is not initialized!";
|
|
|
- return -1;
|
|
|
+ return QByteArray();
|
|
|
}
|
|
|
|
|
|
- Q_ASSERT(output && output->isOpen() && output->isWritable());
|
|
|
- if (!output || !output->isOpen() || !output->isWritable()) {
|
|
|
+ Q_ASSERT(buffer.isOpen() && buffer.isWritable());
|
|
|
+ if (!buffer.isOpen() || !buffer.isWritable()) {
|
|
|
qCritical(lcCse()) << "Decryption failed. Incorrect output device!";
|
|
|
- return -1;
|
|
|
+ return QByteArray();
|
|
|
}
|
|
|
|
|
|
Q_ASSERT(input);
|
|
|
if (!input) {
|
|
|
qCritical(lcCse()) << "Decryption failed. Incorrect input!";
|
|
|
- return -1;
|
|
|
+ return QByteArray();
|
|
|
}
|
|
|
|
|
|
Q_ASSERT(chunkSize > 0);
|
|
|
if (chunkSize <= 0) {
|
|
|
qCritical(lcCse()) << "Decryption failed. Incorrect chunkSize!";
|
|
|
- return -1;
|
|
|
+ return QByteArray();
|
|
|
}
|
|
|
|
|
|
if (_decryptedSoFar == 0) {
|
|
|
@@ -1840,47 +1844,54 @@ qint32 EncryptionHelper::StreamingDecryptor::chunkDecryption(const char *input,
|
|
|
Q_ASSERT(_decryptedSoFar + chunkSize <= _totalSize);
|
|
|
if (_decryptedSoFar + chunkSize > _totalSize) {
|
|
|
qCritical(lcCse()) << "Decryption failed. Chunk is out of range!";
|
|
|
- return -1;
|
|
|
+ return QByteArray();
|
|
|
+ }
|
|
|
+
|
|
|
+ Q_ASSERT(_decryptedSoFar + chunkSize < OCC::Constants::e2EeTagSize || _totalSize - OCC::Constants::e2EeTagSize >= _decryptedSoFar + chunkSize - OCC::Constants::e2EeTagSize);
|
|
|
+ if (_decryptedSoFar + chunkSize > OCC::Constants::e2EeTagSize && _totalSize - OCC::Constants::e2EeTagSize < _decryptedSoFar + chunkSize - OCC::Constants::e2EeTagSize) {
|
|
|
+ qCritical(lcCse()) << "Decryption failed. Incorrect chunk!";
|
|
|
+ return QByteArray();
|
|
|
}
|
|
|
|
|
|
const bool isLastChunk = _decryptedSoFar + chunkSize == _totalSize;
|
|
|
|
|
|
- // last OCC::CommonConstants::e2EeTagSize bytes is ALWAYS a tag!!!
|
|
|
- const qint32 size = isLastChunk ? static_cast<qint32>(chunkSize) - OCC::CommonConstants::e2EeTagSize : static_cast<qint32>(chunkSize);
|
|
|
+ // last OCC::Constants::e2EeTagSize bytes is ALWAYS a e2EeTag!!!
|
|
|
+ const qint64 size = isLastChunk ? chunkSize - OCC::Constants::e2EeTagSize : chunkSize;
|
|
|
|
|
|
- Q_ASSERT(size > 0);
|
|
|
- if (size <= 0) {
|
|
|
+ // either the size is more than 0 and an e2EeTag is at the end of chunk, or, chunk is the e2EeTag itself
|
|
|
+ Q_ASSERT(size > 0 || chunkSize == OCC::Constants::e2EeTagSize);
|
|
|
+ if (size <= 0 && chunkSize != OCC::Constants::e2EeTagSize) {
|
|
|
qCritical(lcCse()) << "Decryption failed. Invalid input size: " << size << " !";
|
|
|
- return -1;
|
|
|
+ return QByteArray();
|
|
|
}
|
|
|
|
|
|
- int bytesWritten = 0;
|
|
|
+ qint64 bytesWritten = 0;
|
|
|
+ qint64 inputPos = 0;
|
|
|
|
|
|
- QByteArray decryptedBlock(blockSize + OCC::CommonConstants::e2EeTagSize - 1, '\0');
|
|
|
- int inputPos = 0;
|
|
|
+ QByteArray decryptedBlock(blockSize + OCC::Constants::e2EeTagSize - 1, '\0');
|
|
|
|
|
|
while(inputPos < size) {
|
|
|
// read blockSize or less bytes
|
|
|
- const QByteArray encryptedBlock = QByteArray(input + inputPos, qMin(size - inputPos, blockSize));
|
|
|
+ const QByteArray encryptedBlock(input + inputPos, qMin(size - inputPos, blockSize));
|
|
|
|
|
|
if (encryptedBlock.size() == 0) {
|
|
|
qCritical(lcCse()) << "Could not read data from the input buffer.";
|
|
|
- return -1;
|
|
|
+ return QByteArray();
|
|
|
}
|
|
|
|
|
|
int outLen = 0;
|
|
|
|
|
|
if(!EVP_DecryptUpdate(_ctx, unsignedData(decryptedBlock), &outLen, reinterpret_cast<const unsigned char*>(encryptedBlock.data()), encryptedBlock.size())) {
|
|
|
qCritical(lcCse()) << "Could not decrypt";
|
|
|
- return -1;
|
|
|
+ return QByteArray();
|
|
|
}
|
|
|
|
|
|
- const auto writtenToOutput = output->write(decryptedBlock, outLen);
|
|
|
+ const auto writtenToOutput = buffer.write(decryptedBlock, outLen);
|
|
|
|
|
|
Q_ASSERT(writtenToOutput == outLen);
|
|
|
if (writtenToOutput != outLen) {
|
|
|
qCritical(lcCse()) << "Failed to write decrypted data to device.";
|
|
|
- return -1;
|
|
|
+ return QByteArray();
|
|
|
}
|
|
|
|
|
|
bytesWritten += writtenToOutput;
|
|
|
@@ -1892,51 +1903,49 @@ qint32 EncryptionHelper::StreamingDecryptor::chunkDecryption(const char *input,
|
|
|
}
|
|
|
|
|
|
if (isLastChunk) {
|
|
|
- // if it's a last chunk, we'd need to read a tag at the end and finalize the decryption
|
|
|
+ // if it's a last chunk, we'd need to read a e2EeTag at the end and finalize the decryption
|
|
|
|
|
|
- Q_ASSERT(chunkSize - inputPos == OCC::CommonConstants::e2EeTagSize);
|
|
|
- if (chunkSize - inputPos != OCC::CommonConstants::e2EeTagSize) {
|
|
|
- qCritical(lcCse()) << "Decryption failed. E2EE tag is missing!";
|
|
|
- return -1;
|
|
|
+ Q_ASSERT(chunkSize - inputPos == OCC::Constants::e2EeTagSize);
|
|
|
+ if (chunkSize - inputPos != OCC::Constants::e2EeTagSize) {
|
|
|
+ qCritical(lcCse()) << "Decryption failed. e2EeTag is missing!";
|
|
|
+ return QByteArray();
|
|
|
}
|
|
|
|
|
|
int outLen = 0;
|
|
|
|
|
|
- QByteArray tag = QByteArray(input + inputPos, OCC::CommonConstants::e2EeTagSize);
|
|
|
+ QByteArray e2EeTag = QByteArray(input + inputPos, OCC::Constants::e2EeTagSize);
|
|
|
|
|
|
- /* Set expected tag value. Works in OpenSSL 1.0.1d and later */
|
|
|
- if(!EVP_CIPHER_CTX_ctrl(_ctx, EVP_CTRL_GCM_SET_TAG, tag.size(), reinterpret_cast<unsigned char*>(tag.data()))) {
|
|
|
- qCritical(lcCse()) << "Could not set expected tag";
|
|
|
- return -1;
|
|
|
+ /* Set expected e2EeTag value. Works in OpenSSL 1.0.1d and later */
|
|
|
+ if(!EVP_CIPHER_CTX_ctrl(_ctx, EVP_CTRL_GCM_SET_TAG, e2EeTag.size(), reinterpret_cast<unsigned char*>(e2EeTag.data()))) {
|
|
|
+ qCritical(lcCse()) << "Could not set expected e2EeTag";
|
|
|
+ return QByteArray();
|
|
|
}
|
|
|
|
|
|
if(1 != EVP_DecryptFinal_ex(_ctx, unsignedData(decryptedBlock), &outLen)) {
|
|
|
qCritical(lcCse()) << "Could finalize decryption";
|
|
|
- return -1;
|
|
|
+ return QByteArray();
|
|
|
}
|
|
|
|
|
|
- const auto writtenToOutput = output->write(decryptedBlock, outLen);
|
|
|
+ const auto writtenToOutput = buffer.write(decryptedBlock, outLen);
|
|
|
|
|
|
Q_ASSERT(writtenToOutput == outLen);
|
|
|
if (writtenToOutput != outLen) {
|
|
|
qCritical(lcCse()) << "Failed to write decrypted data to device.";
|
|
|
- return -1;
|
|
|
+ return QByteArray();
|
|
|
}
|
|
|
|
|
|
bytesWritten += writtenToOutput;
|
|
|
|
|
|
- _decryptedSoFar += OCC::CommonConstants::e2EeTagSize;
|
|
|
+ _decryptedSoFar += OCC::Constants::e2EeTagSize;
|
|
|
|
|
|
_isFinished = true;
|
|
|
}
|
|
|
|
|
|
- // qCDebug(lcCse()) <<"Decrypting:" << _decryptedSoFar << "/" << _totalSize;
|
|
|
-
|
|
|
if (isFinished()) {
|
|
|
qCDebug(lcCse()) << "Decryption complete";
|
|
|
}
|
|
|
|
|
|
- return bytesWritten;
|
|
|
+ return byteArray;
|
|
|
}
|
|
|
|
|
|
bool EncryptionHelper::StreamingDecryptor::isInitialized() const
|