Initial commit
[keepassx] / src / lib / SecString.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005 by Tarek Saidi                                     *
3  *   tarek@linux                                                           *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; version 2 of the License.               *
8
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20
21 CArcFour SecString::RC4;
22 quint8* SecString::sessionkey;
23
24 SecString::operator QString(){
25         return string();
26 }
27
28 SecString::SecString(){
29         locked=true;
30 }
31
32 int SecString::length(){
33         return crypt.size();
34 }
35
36 SecString::~SecString(){
37         lock();
38 }
39
40 void SecString::lock(){
41         locked=true;
42         overwrite(plain);
43         plain=QString();
44 }
45
46 void SecString::unlock(){
47         locked = false;
48         plain = QString();
49         if(!crypt.length())
50                 return;
51         const unsigned char* buffer = new unsigned char[crypt.length()];
52         RC4.decrypt( (quint8*)crypt.data(), (unsigned char*)buffer, crypt.length() );
53         plain = QString::fromUtf8((const char*)buffer, crypt.size());
54         overwrite((unsigned char*)buffer, crypt.size());
55         delete [] buffer;
56 }
57
58 const QString& SecString::string(){
59         Q_ASSERT_X(!locked, "SecString::string()", "string is locked");
60         return plain;
61 }
62
63 void SecString::setString(QString& str, bool DeleteSource){
64         QByteArray StrData = str.toUtf8();
65         int len = StrData.size();
66         unsigned char* buffer = new unsigned char[len];
67         RC4.encrypt((const unsigned char*)StrData.data(), buffer, len);
68         crypt = QByteArray((const char*)buffer, len);
69         overwrite(buffer, len);
70         overwrite((unsigned char*)StrData.data(), len);
71         delete [] buffer;
72         if(DeleteSource){
73                 overwrite(str);
74                 str=QString();
75         }
76         lock();
77 }
78
79 void SecString::overwrite(unsigned char* str, int strlen){
80         if(strlen==0 || str==NULL)
81                 return;
82         
83         for(int i=0; i<strlen; i++)
84                 str[i]=0;
85 }
86
87 void SecString::overwrite(QString& str){
88         for (int i=0; i<str.length(); i++) {
89                 str[i] = '\0';
90         }
91 }
92
93 void SecString::generateSessionKey(){
94         sessionkey = new quint8[32];
95         if (!lockPage(sessionkey, 32))
96                 qDebug("Failed to lock session key page");
97         randomize(sessionkey, 32);
98         RC4.setKey(sessionkey, 32);
99 }
100
101 void SecString::deleteSessionKey() {
102         overwrite(sessionkey, 32);
103         unlockPage(sessionkey, 32);
104         delete[] sessionkey;
105 }
106
107
108 SecData::SecData(int len) : locked(true){
109         length = len;
110         data = new quint8[len];
111 }
112
113 SecData::~SecData(){
114         if (!locked){
115                 for (int i=0; i<length; i++)
116                         data[i] = 0;
117         }
118         delete[] data;
119 }
120
121 void SecData::lock(){
122         Q_ASSERT(!locked);
123         SecString::RC4.encrypt(data, data, length);
124         locked = true;
125 }
126
127 void SecData::unlock(){
128         Q_ASSERT(locked);
129         SecString::RC4.decrypt(data, data, length);
130         locked = false;
131 }
132
133 void SecData::copyData(quint8* src){
134         locked = false;
135         memcpy(data, src, length);
136         lock();
137 }
138
139 void SecData::copyData(SecData& secData){
140         secData.unlock();
141         copyData(*secData);
142         secData.lock();
143 }
144
145 quint8* SecData::operator*(){
146         Q_ASSERT(!locked);
147         return data;
148 }