1 //**********************************************************************************
2 //EncryptPad Copyright 2016 Evgeny Pokhilko
3 //<http://www.evpo.net/encryptpad>
4 //
5 //This file is part of EncryptPad
6 //
7 //EncryptPad is free software: you can redistribute it and/or modify
8 //it under the terms of the GNU General Public License as published by
9 //the Free Software Foundation, either version 2 of the License, or
10 //(at your option) any later version.
11 //
12 //EncryptPad is distributed in the hope that it will be useful,
13 //but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 //GNU General Public License for more details.
16 //
17 //You should have received a copy of the GNU General Public License
18 //along with EncryptPad.  If not, see <http://www.gnu.org/licenses/>.
19 //**********************************************************************************
20 #include "encryptor.h"
21 #include <string>
22 #include "file_encryption.h"
23 #include "file_helper.h"
24 #include "plog/Log.h"
25 
26 using namespace std;
27 using namespace EncryptPadEncryptor;
28 using namespace EncryptPad;
29 using namespace Botan;
30 
SetLibcurlParams(const std::string & params)31 void Encryptor::SetLibcurlParams(const std::string &params)
32 {
33     mLibcurlParams = params;
34 }
35 
SetLibcurlPath(const std::string & path)36 void Encryptor::SetLibcurlPath(const std::string &path)
37 {
38     mLibcurlPath = path;
39 }
40 
SetEncryptedPlainSwitchFunctor(EncryptedPlainSwitchFunctor * functor)41 void Encryptor::SetEncryptedPlainSwitchFunctor(EncryptedPlainSwitchFunctor *functor)
42 {
43     mEncryptedPlainSwitchFunctor = functor;
44 }
45 
ClearKFPassphrase()46 void Encryptor::ClearKFPassphrase()
47 {
48     kf_key_service_.Clear();
49 }
50 
HasKFPassphrase() const51 bool Encryptor::HasKFPassphrase() const
52 {
53     return kf_key_service_.IsPassphraseSet();
54 }
55 
SetIsPlainText()56 void Encryptor::SetIsPlainText()
57 {
58     key_service_.Clear();
59 	mPlainText = true;
60 	if (mEncryptedPlainSwitchFunctor)
61 		mEncryptedPlainSwitchFunctor->EncryptedPlainSwitchChange(false);
62 }
63 
GetIsPlainText()64 bool Encryptor::GetIsPlainText()
65 {
66     return this->mPlainText;
67 }
68 
UnusedKeysExist()69 bool Encryptor::UnusedKeysExist()
70 {
71     return key_service_.UnusedKeysExist();
72 }
73 
GetX2KeyLocation() const74 const string &Encryptor::GetX2KeyLocation() const
75 {
76 	return this->mX2KeyLocation;
77 }
78 
SetPassphrase(const char * pwd,EncryptPad::PacketMetadata * metadata)79 void Encryptor::SetPassphrase(const char *pwd, EncryptPad::PacketMetadata *metadata)
80 {
81     assert(metadata);
82     key_service_.Clear();
83     if(metadata)
84     {
85         std::string passphrase(pwd);
86         key_service_.ChangePassphrase(
87                 passphrase,
88                 metadata->hash_algo,
89                 GetAlgoSpec(metadata->cipher_algo).key_size,
90                 metadata->iterations);
91         std::fill(std::begin(passphrase), std::end(passphrase), '0');
92 
93         // if there was key_only before, switch it off
94         metadata->key_only = false;
95     }
96 
97 	mPlainText = false;
98 
99 	if (mEncryptedPlainSwitchFunctor)
100 		mEncryptedPlainSwitchFunctor->EncryptedPlainSwitchChange(true);
101 }
102 
Save(const string & fileName,const SecureVector<byte> & content,const string & x2KeyLocation,bool persistX2KeyLocation,PacketMetadata * metadata,const std::string * kf_passphrase)103 EpadResult Encryptor::Save(const string &fileName, const SecureVector<byte> &content,
104         const string &x2KeyLocation, bool persistX2KeyLocation,
105         PacketMetadata *metadata, const std::string *kf_passphrase)
106 {
107     using namespace EncryptPad;
108 
109     bool is_protected = !GetIsPlainText() || !x2KeyLocation.empty();
110 
111     if(!is_protected)
112     {
113         LOG_INFO << "the file is not protected";
114         OutPacketStreamFile file;
115         if (OpenFile(fileName, file) != OpenFileResult::OK)
116         {
117             return EpadResult::IOErrorOutput;
118         }
119         LOG_INFO << "unprotected file opened";
120 
121         if(!file.Write(content.data(), content.size()))
122         {
123             return EpadResult::IOErrorOutput;
124         }
125         LOG_INFO << "unprotected file written";
126 
127         return EpadResult::Success;
128     }
129 
130     assert(metadata);
131     mX2KeyLocation = x2KeyLocation;
132     metadata->key_file = mX2KeyLocation;
133 
134     if(GetIsPlainText())
135         metadata->key_only = true;
136 
137     metadata->persist_key_path = persistX2KeyLocation;
138 
139     EncryptParams enc_params = {};
140     enc_params.key_service = &key_service_;
141     enc_params.libcurl_path = &mLibcurlPath;
142     enc_params.libcurl_parameters = &mLibcurlParams;
143 
144     EncryptParams kf_encrypt_params = {};
145 
146     if(kf_passphrase || kf_key_service_.IsPassphraseSet())
147     {
148         kf_encrypt_params.key_service = &kf_key_service_;
149         kf_encrypt_params.passphrase = kf_passphrase;
150         enc_params.key_file_encrypt_params = &kf_encrypt_params;
151     }
152 
153     LOG_INFO << "calling EncryptPacketFile";
154     EpadResult result = EncryptPacketFile(content, fileName, enc_params, *metadata);
155 
156     if(result != EpadResult::Success)
157     {
158         LOG_ERROR << "EncryptPacketFile failed";
159         return result;
160     }
161 
162     if(metadata->key_only)
163         this->SetIsPlainText();
164 
165     LOG_INFO << "EncryptPacketFile succeeded";
166     return result;
167 }
168 
169 // Loads file, decrypts into content
Load(const std::string & fileName,SecureVector<byte> & content,const string & x2KeyLocation,const string * passphrase,EncryptPad::PacketMetadata * metadata,const string * kf_passphrase)170 EpadResult Encryptor::Load(const std::string &fileName, SecureVector<byte> &content,
171         const string &x2KeyLocation, const string *passphrase,
172         EncryptPad::PacketMetadata *metadata, const string *kf_passphrase)
173 {
174     using namespace EncryptPad;
175 
176     bool is_protected = !GetIsPlainText() || !x2KeyLocation.empty();
177     if(!is_protected)
178     {
179         InPacketStreamFile file;
180         if (OpenFile(fileName, file) != OpenFileResult::OK)
181         {
182             return EpadResult::IOErrorInput;
183         }
184 
185         content.resize(file.GetCount());
186         stream_length_type length = file.Read(content.data(), content.size());
187         if(length != static_cast<stream_length_type>(content.size()))
188             return EpadResult::IOErrorInput;
189 
190         mX2KeyLocation = x2KeyLocation;
191         return EpadResult::Success;
192     }
193 
194     assert(metadata);
195     mX2KeyLocation = x2KeyLocation;
196     metadata->key_file = mX2KeyLocation;
197 
198     EncryptParams enc_params = {};
199     enc_params.passphrase = passphrase;
200     enc_params.key_service = &key_service_;
201     enc_params.libcurl_path = &mLibcurlPath;
202     enc_params.libcurl_parameters = &mLibcurlParams;
203 
204     EncryptParams kf_encrypt_params = {};
205 
206     if(kf_passphrase || kf_key_service_.IsPassphraseSet())
207     {
208         kf_encrypt_params.key_service = &kf_key_service_;
209         kf_encrypt_params.passphrase = kf_passphrase;
210         enc_params.key_file_encrypt_params = &kf_encrypt_params;
211     }
212 
213     EpadResult result = DecryptPacketFile(fileName, enc_params, content, *metadata);
214     if(result != EpadResult::Success)
215         return result;
216     mX2KeyLocation = metadata->key_file;
217     if(metadata->key_only)
218         this->SetIsPlainText();
219 
220     return result;
221 }
222 
223