Skip to content

Commit 59544c3

Browse files
committed
Avoid creating full memory copy on encrypting
Signed-off-by: Raul Metsma <[email protected]>
1 parent 57c7216 commit 59544c3

File tree

6 files changed

+244
-296
lines changed

6 files changed

+244
-296
lines changed

cdoc/CDoc1Writer.cpp

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@
2626
#include "XmlWriter.h"
2727
#include "utils/memory.h"
2828

29-
#define OPENSSL_SUPPRESS_DEPRECATED
30-
3129
#include <openssl/x509.h>
3230

3331
using namespace libcdoc;
@@ -94,7 +92,8 @@ int64_t CDoc1Writer::Private::writeEncryptionProperties(bool use_ddoc)
9492

9593
int64_t CDoc1Writer::Private::writeKeyInfo(bool use_ddoc, const Crypto::Key& transportKey)
9694
{
97-
RET_ERROR(writeStartElement(Private::DENC, "EncryptedData", {{"MimeType", use_ddoc ? "http://www.sk.ee/DigiDoc/v1.3.0/digidoc.xsd" : "application/octet-stream"}}));
95+
RET_ERROR(writeStartElement(Private::DENC, "EncryptedData",
96+
{{"MimeType", use_ddoc ? "http://www.sk.ee/DigiDoc/v1.3.0/digidoc.xsd" : "application/octet-stream"}}));
9897
RET_ERROR(writeElement(Private::DENC, "EncryptionMethod", {{"Algorithm", method}}));
9998
return writeElement(Private::DS, "KeyInfo", {}, [&]() -> int64_t {
10099
for (const Recipient& key : rcpts) {
@@ -143,10 +142,7 @@ int64_t CDoc1Writer::Private::writeRecipient(const std::vector<uint8_t> &recipie
143142
{
144143
case EVP_PKEY_RSA:
145144
{
146-
auto rsa = make_unique_ptr<RSA_free>(EVP_PKEY_get1_RSA(peerPKey));
147-
encryptedData.resize(size_t(RSA_size(rsa.get())));
148-
RSA_public_encrypt(int(transportKey.key.size()), transportKey.key.data(),
149-
encryptedData.data(), rsa.get(), RSA_PKCS1_PADDING);
145+
encryptedData = Crypto::encrypt(peerPKey, RSA_PKCS1_PADDING, transportKey.key);
150146
RET_ERROR(writeElement(Private::DENC, "EncryptionMethod", {{"Algorithm", Crypto::RSA_MTH}}));
151147
RET_ERROR(writeElement(Private::DS, "KeyInfo", [&] {
152148
return writeElement(Private::DS, "X509Data", [&] {
@@ -156,18 +152,18 @@ int64_t CDoc1Writer::Private::writeRecipient(const std::vector<uint8_t> &recipie
156152
break;
157153
}
158154
case EVP_PKEY_EC:
159-
{
160-
auto *peerECKey = EVP_PKEY_get0_EC_KEY(peerPKey);
161-
int curveName = EC_GROUP_get_curve_name(EC_KEY_get0_group(peerECKey));
162-
auto priv = make_unique_ptr<EC_KEY_free>(EC_KEY_new_by_curve_name(curveName));
163-
EC_KEY_generate_key(priv.get());
164-
auto pkey = make_unique_ptr<EVP_PKEY_free>(EVP_PKEY_new());
165-
EVP_PKEY_set1_EC_KEY(pkey.get(), priv.get());
166-
std::vector<uint8_t> sharedSecret = libcdoc::Crypto::deriveSharedSecret(pkey.get(), peerPKey);
167-
168-
std::string oid(50, 0);
169-
oid.resize(size_t(OBJ_obj2txt(&oid[0], int(oid.size()), OBJ_nid2obj(curveName), 1)));
170-
std::vector<uint8_t> SsDer = Crypto::toPublicKeyDer(pkey.get());
155+
{
156+
auto ephKey = libcdoc::Crypto::genECKey(peerPKey);
157+
std::vector<uint8_t> sharedSecret = libcdoc::Crypto::deriveSharedSecret(ephKey.get(), peerPKey);
158+
159+
std::string groupName(25, 0);
160+
size_t len = 0;
161+
EVP_PKEY_get_group_name(ephKey.get(), groupName.data(), groupName.size(), &len);
162+
groupName.resize(len);
163+
auto obj = make_unique_ptr<ASN1_OBJECT_free>(OBJ_txt2obj(groupName.c_str(), 0));
164+
std::string oid(25, 0);
165+
oid.resize(size_t(OBJ_obj2txt(oid.data(), int(oid.size()), obj.get(), 1)));
166+
std::vector<uint8_t> SsDer = Crypto::toPublicKeyDer(ephKey.get());
171167

172168
std::string encryptionMethod(libcdoc::Crypto::KWAES256_MTH);
173169
std::string concatDigest = libcdoc::Crypto::SHA384_MTH;
@@ -245,10 +241,11 @@ CDoc1Writer::encrypt(libcdoc::MultiDataSource& src, const std::vector<libcdoc::R
245241
std::vector<uint8_t> data;
246242
data.reserve(16384);
247243
VectorConsumer vcons(data);
244+
EncryptionConsumer enc(vcons, d->method, transportKey);
248245
std::string name;
249246
int64_t size;
250247
if(use_ddoc) {
251-
DDOCWriter ddoc(vcons);
248+
DDOCWriter ddoc(enc);
252249
result_t result;
253250
for (result = src.next(name, size); result == OK; result = src.next(name, size)) {
254251
std::vector<uint8_t> contents;
@@ -262,13 +259,14 @@ CDoc1Writer::encrypt(libcdoc::MultiDataSource& src, const std::vector<libcdoc::R
262259
return result;
263260
} else {
264261
RET_ERROR(src.next(name, size));
265-
if(auto rv = src.readAll(vcons); rv >= 0)
262+
if(auto rv = src.readAll(enc); rv >= 0)
266263
d->files.push_back({std::move(name), size_t(rv)});
267264
else
268265
return rv;
269266
}
267+
RET_ERROR(enc.close());
270268
RET_ERROR(vcons.close());
271-
return d->writeBase64Element(Private::DENC, "CipherValue", libcdoc::Crypto::encrypt(d->method, transportKey, data));
269+
return d->writeBase64Element(Private::DENC, "CipherValue", data);
272270
}));
273271
RET_ERROR(d->writeEncryptionProperties(use_ddoc));
274272
d.reset();
@@ -322,16 +320,20 @@ CDoc1Writer::finishEncryption()
322320

323321
RET_ERROR(d->writeKeyInfo(use_ddoc, transportKey));
324322
RET_ERROR(d->writeElement(Private::DENC, "CipherData", [&] {
325-
if(!use_ddoc)
326-
return d->writeBase64Element(Private::DENC, "CipherValue", libcdoc::Crypto::encrypt(d->method, transportKey, d->files.back().data));
327323
std::vector<uint8_t> data;
328324
data.reserve(16384);
329325
VectorConsumer vcons(data);
330-
for (DDOCWriter ddoc(vcons); const FileEntry& file : d->files) {
331-
RET_ERROR(ddoc.addFile(file.name, "application/octet-stream", file.data));
326+
EncryptionConsumer enc(vcons, d->method, transportKey);
327+
if(use_ddoc)
328+
{
329+
for(DDOCWriter ddoc(enc); const FileEntry& file : d->files)
330+
RET_ERROR(ddoc.addFile(file.name, "application/octet-stream", file.data));
332331
}
332+
else
333+
RET_ERROR(VectorSource(d->files.back().data).readAll(enc));
334+
RET_ERROR(enc.close());
333335
RET_ERROR(vcons.close());
334-
return d->writeBase64Element(Private::DENC, "CipherValue", libcdoc::Crypto::encrypt(d->method, transportKey, data));
336+
return d->writeBase64Element(Private::DENC, "CipherValue", data);
335337
}));
336338
RET_ERROR(d->writeEncryptionProperties(use_ddoc));
337339
d.reset();

0 commit comments

Comments
 (0)