1 /*
2     SPDX-FileCopyrightText: 2006, 2007 Jimmy Gilles <jimmygilles@gmail.com>
3     SPDX-FileCopyrightText: 2007, 2008, 2009, 2010, 2012, 2013, 2014, 2017 Rolf Eike Beer <kde@opensource.sf-tec.de>
4     SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "kgpgkey.h"
8 
9 #include "convert.h"
10 
11 #include <QStringList>
12 
13 namespace KgpgCore
14 {
15 
_describe_key_strength(KgpgKeyAlgo algorithm,const uint size,const QString & curve)16 static QString _describe_key_strength(KgpgKeyAlgo algorithm, const uint size, const QString &curve)
17 {
18     if (!curve.isEmpty())
19         return curve;
20 
21     QString prefix;
22 
23     switch(algorithm)
24     {
25     case ALGO_RSA: prefix = QStringLiteral("rsa"); break;
26     case ALGO_ELGAMAL: prefix = QStringLiteral("elg"); break;
27     case ALGO_DSA: prefix = QStringLiteral("dsa"); break;
28     }
29 
30     return prefix + QString::number(size);
31 }
32 
33 //BEGIN KeySub
KgpgKeySubPrivate(const QString & id,const uint size,const KgpgKeyTrust trust,const KgpgKeyAlgo algo,const KgpgSubKeyType type,const QDateTime & date,const QString & curve)34 KgpgKeySubPrivate::KgpgKeySubPrivate(const QString &id, const uint size, const KgpgKeyTrust trust, const KgpgKeyAlgo algo,
35                                      const KgpgSubKeyType type, const QDateTime &date, const QString &curve)
36     : gpgsubvalid(false),
37     gpgsubid(id),
38     gpgsubsize(size),
39     gpgsubcreation(date),
40     gpgsubtrust(trust),
41     gpgsubalgo(algo),
42     gpgsubtype(type),
43     gpgcurve(curve)
44 {
45 }
46 
operator ==(const KgpgKeySubPrivate & other) const47 bool KgpgKeySubPrivate::operator==(const KgpgKeySubPrivate &other) const
48 {
49     if (gpgsubvalid != other.gpgsubvalid) return false;
50     if (gpgsubalgo != other.gpgsubalgo) return false;
51     if (gpgsubid != other.gpgsubid) return false;
52     if (gpgsubsize != other.gpgsubsize) return false;
53     if (gpgsubexpiration != other.gpgsubexpiration) return false;
54     if (gpgsubcreation != other.gpgsubcreation) return false;
55     if (gpgsubtrust != other.gpgsubtrust) return false;
56     if (gpgsubtype != other.gpgsubtype) return false;
57     return true;
58 }
59 
KgpgKeySub(const QString & id,const uint size,const KgpgKeyTrust trust,const KgpgKeyAlgo algo,const KgpgSubKeyType type,const QDateTime & date,const QString & curve)60 KgpgKeySub::KgpgKeySub(const QString &id, const uint size, const KgpgKeyTrust trust, const KgpgKeyAlgo algo, const KgpgSubKeyType type,
61                        const QDateTime &date, const QString &curve)
62     : d(new KgpgKeySubPrivate(id, size, trust, algo, type, date, curve))
63 {
64 }
65 
KgpgKeySub(const KgpgKeySub & other)66 KgpgKeySub::KgpgKeySub(const KgpgKeySub &other)
67 {
68     d = other.d;
69 }
70 
setExpiration(const QDateTime & date)71 void KgpgKeySub::setExpiration(const QDateTime &date)
72 {
73     d->gpgsubexpiration = date;
74 }
75 
setValid(const bool valid)76 void KgpgKeySub::setValid(const bool valid)
77 {
78     d->gpgsubvalid = valid;
79 }
80 
id() const81 QString KgpgKeySub::id() const
82 {
83     return d->gpgsubid;
84 }
85 
size() const86 uint KgpgKeySub::size() const
87 {
88     return d->gpgsubsize;
89 }
90 
strength() const91 QString KgpgKeySub::strength() const
92 {
93     return _describe_key_strength(algorithm(), size(), d->gpgcurve);
94 }
95 
unlimited() const96 bool KgpgKeySub::unlimited() const
97 {
98     return d->gpgsubexpiration.isNull();
99 }
100 
expirationDate() const101 QDateTime KgpgKeySub::expirationDate() const
102 {
103     return d->gpgsubexpiration;
104 }
105 
creationDate() const106 QDateTime KgpgKeySub::creationDate() const
107 {
108     return d->gpgsubcreation;
109 }
110 
trust() const111 KgpgKeyTrust KgpgKeySub::trust() const
112 {
113     return d->gpgsubtrust;
114 }
115 
algorithm() const116 KgpgKeyAlgo KgpgKeySub::algorithm() const
117 {
118     return d->gpgsubalgo;
119 }
120 
valid() const121 bool KgpgKeySub::valid() const
122 {
123     return d->gpgsubvalid;
124 }
125 
type() const126 KgpgSubKeyType KgpgKeySub::type() const
127 {
128     return d->gpgsubtype;
129 }
130 
curve() const131 QString KgpgKeySub::curve() const
132 {
133     return d->gpgcurve;
134 }
135 
operator ==(const KgpgKeySub & other) const136 bool KgpgKeySub::operator==(const KgpgKeySub &other) const
137 {
138     if (d == other.d) return true;
139     if ((*d) == (*(other.d))) return true;
140     return false;
141 }
142 
operator =(const KgpgKeySub & other)143 KgpgKeySub& KgpgKeySub::operator=(const KgpgKeySub &other)
144 {
145     d = other.d;
146     return *this;
147 }
148 
149 //END KeySub
150 
151 
152 //BEGIN Key
153 
KgpgKeyPrivate(const QString & id,const uint size,const KgpgKeyTrust trust,const KgpgKeyAlgo algo,const KgpgSubKeyType subtype,const KgpgSubKeyType keytype,const QDateTime & creationDate,const QString & curve)154 KgpgKeyPrivate::KgpgKeyPrivate(const QString &id, const uint size, const KgpgKeyTrust trust, const KgpgKeyAlgo algo, const KgpgSubKeyType subtype,
155                                const KgpgSubKeyType keytype, const QDateTime &creationDate, const QString &curve)
156     : gpgkeysecret(false),
157     gpgkeyvalid(false),
158     gpgkeyid(id),
159     gpgkeysize(size),
160     gpgkeytrust(trust),
161     gpgkeycreation(creationDate),
162     gpgkeyalgo(algo),
163     gpgsubtype(subtype),
164     gpgkeytype(keytype),
165     gpgcurve(curve),
166     gpgsublist(new KgpgKeySubList())
167 {
168 }
169 
operator ==(const KgpgKeyPrivate & other) const170 bool KgpgKeyPrivate::operator==(const KgpgKeyPrivate &other) const
171 {
172     if (gpgkeysecret != other.gpgkeysecret) return false;
173     if (gpgkeyvalid != other.gpgkeyvalid) return false;
174     if (gpgkeymail != other.gpgkeymail) return false;
175     if (gpgkeyname != other.gpgkeyname) return false;
176     if (gpgkeycomment != other.gpgkeycomment) return false;
177     if (gpgkeyfingerprint != other.gpgkeyfingerprint) return false;
178     if (gpgkeyid != other.gpgkeyid) return false;
179     if (gpgkeysize != other.gpgkeysize) return false;
180     if (gpgkeyownertrust != other.gpgkeyownertrust) return false;
181     if (gpgkeytrust != other.gpgkeytrust) return false;
182     if (gpgkeycreation != other.gpgkeycreation) return false;
183     if (gpgkeyexpiration != other.gpgkeyexpiration) return false;
184     if (gpgkeyalgo != other.gpgkeyalgo) return false;
185     if (gpgsubtype != other.gpgsubtype) return false;
186     if (gpgkeytype != other.gpgkeytype) return false;
187     if (gpgsublist != other.gpgsublist) return false;
188     return true;
189 }
190 
KgpgKey(const QString & id,const uint size,const KgpgKeyTrust trust,const KgpgKeyAlgo algo,const KgpgSubKeyType subtype,const KgpgSubKeyType keytype,const QDateTime & creationDate,const QString & curve)191 KgpgKey::KgpgKey(const QString &id, const uint size, const KgpgKeyTrust trust, const KgpgKeyAlgo algo, const KgpgSubKeyType subtype,
192                  const KgpgSubKeyType keytype, const QDateTime &creationDate, const QString &curve)
193     : d(new KgpgKeyPrivate(id, size, trust, algo, subtype, keytype, creationDate, curve))
194 {
195 }
196 
KgpgKey(const KgpgKey & other)197 KgpgKey::KgpgKey(const KgpgKey &other)
198 {
199     d = other.d;
200 }
201 
setSecret(const bool secret)202 void KgpgKey::setSecret(const bool secret)
203 {
204     d->gpgkeysecret = secret;
205 }
206 
setValid(const bool valid)207 void KgpgKey::setValid(const bool valid)
208 {
209     d->gpgkeyvalid = valid;
210 }
211 
setName(const QString & name)212 void KgpgKey::setName(const QString &name)
213 {
214     d->gpgkeyname = name;
215 }
216 
setEmail(const QString & email)217 void KgpgKey::setEmail(const QString &email)
218 {
219     d->gpgkeymail = email;
220 }
221 
setComment(const QString & comment)222 void KgpgKey::setComment(const QString &comment)
223 {
224     d->gpgkeycomment = comment;
225 }
226 
setFingerprint(const QString & fingerprint)227 void KgpgKey::setFingerprint(const QString &fingerprint)
228 {
229     d->gpgkeyfingerprint = fingerprint;
230 }
231 
setOwnerTrust(const gpgme_validity_t owtrust)232 void KgpgKey::setOwnerTrust(const gpgme_validity_t owtrust)
233 {
234     d->gpgkeyownertrust = owtrust;
235 }
236 
setExpiration(const QDateTime & date)237 void KgpgKey::setExpiration(const QDateTime &date)
238 {
239     d->gpgkeyexpiration = date;
240 }
241 
secret() const242 bool KgpgKey::secret() const
243 {
244     return d->gpgkeysecret;
245 }
246 
valid() const247 bool KgpgKey::valid() const
248 {
249     return d->gpgkeyvalid;
250 }
251 
id() const252 QString KgpgKey::id() const
253 {
254     return d->gpgkeyid.right(8);
255 }
256 
fullId() const257 QString KgpgKey::fullId() const
258 {
259     return d->gpgkeyid;
260 }
261 
name() const262 QString KgpgKey::name() const
263 {
264     return d->gpgkeyname;
265 }
266 
email() const267 QString KgpgKey::email() const
268 {
269     return d->gpgkeymail;
270 }
271 
comment() const272 QString KgpgKey::comment() const
273 {
274     return d->gpgkeycomment;
275 }
276 
fingerprint() const277 const QString &KgpgKey::fingerprint() const
278 {
279     return d->gpgkeyfingerprint;
280 }
281 
size() const282 uint KgpgKey::size() const
283 {
284     return d->gpgkeysize;
285 }
286 
strength() const287 QString KgpgKey::strength() const
288 {
289     return _describe_key_strength(algorithm(), size(), d->gpgcurve);
290 }
291 
292 /**
293  * @brief find the "best" encryption key
294  *
295  * The "best" is the first one that is not expired, or simply the
296  * first one.
297  */
298 static const KgpgKeySub *
bestEncryptionKey(const KgpgKeySubList & list)299 bestEncryptionKey(const KgpgKeySubList &list)
300 {
301 	const KgpgKeySub *enc = nullptr;
302 	// Get the first encryption subkey
303 	for (const KgpgKeySub &k : list) {
304 		if (k.type() & SKT_ENCRYPTION) {
305 			// if the first encryption subkey is expired
306 			// check if there is one that is not
307 			if (k.trust() > TRUST_EXPIRED)
308 				return &k;
309 			if (enc == nullptr)
310 				enc = &k;
311 		}
312 	}
313 
314 	return enc;
315 }
316 
encryptionSize() const317 uint KgpgKey::encryptionSize() const
318 {
319 	const KgpgKeySub *enc = bestEncryptionKey(*d->gpgsublist);
320 	if (enc != nullptr)
321 		return enc->size();
322 	return 0;
323 }
324 
encryptionStrength() const325 QString KgpgKey::encryptionStrength() const
326 {
327 	const KgpgKeySub *enc = bestEncryptionKey(*d->gpgsublist);
328     if (enc != nullptr)
329         return _describe_key_strength(enc->algorithm(), enc->size(), enc->curve());
330     return QString();
331 }
332 
ownerTrust() const333 gpgme_validity_t KgpgKey::ownerTrust() const
334 {
335     return d->gpgkeyownertrust;
336 }
337 
trust() const338 KgpgKeyTrust KgpgKey::trust() const
339 {
340     return d->gpgkeytrust;
341 }
342 
creationDate() const343 QDateTime KgpgKey::creationDate() const
344 {
345     return d->gpgkeycreation;
346 }
347 
expirationDate() const348 QDateTime KgpgKey::expirationDate() const
349 {
350     return d->gpgkeyexpiration;
351 }
352 
unlimited() const353 bool KgpgKey::unlimited() const
354 {
355     return d->gpgkeyexpiration.isNull();
356 }
357 
algorithm() const358 KgpgKeyAlgo KgpgKey::algorithm() const
359 {
360     return d->gpgkeyalgo;
361 }
362 
encryptionAlgorithm() const363 KgpgKeyAlgo KgpgKey::encryptionAlgorithm() const
364 {
365 	// Get the first encryption subkey
366 	for (const KgpgKeySub &k : qAsConst(*d->gpgsublist))
367 		if (k.type() & SKT_ENCRYPTION)
368 			return k.algorithm();
369 
370 	return ALGO_UNKNOWN;
371 }
372 
subtype() const373 KgpgSubKeyType KgpgKey::subtype() const
374 {
375     return d->gpgsubtype;
376 }
377 
keytype() const378 KgpgSubKeyType KgpgKey::keytype() const
379 {
380 	return d->gpgkeytype;
381 }
382 
curve() const383 QString KgpgKey::curve() const
384 {
385     return d->gpgcurve;
386 }
387 
subList() const388 KgpgKeySubListPtr KgpgKey::subList() const
389 {
390     return d->gpgsublist;
391 }
392 
operator ==(const KgpgKey & other) const393 bool KgpgKey::operator==(const KgpgKey &other) const
394 {
395     if (d == other.d) return true;
396     if ((*d) == (*(other.d))) return true;
397     return false;
398 }
399 
operator =(const KgpgKey & other)400 KgpgKey& KgpgKey::operator=(const KgpgKey &other)
401 {
402     d = other.d;
403     return *this;
404 }
405 
operator QStringList() const406 KgpgKeyList::operator QStringList() const
407 {
408     QStringList res;
409     res.reserve(count());
410 
411     for (const KgpgKey &key : *this)
412         res << key.fullId();
413 
414     return res;
415 }
416 
417 //END Key
418 
419 } // namespace KgpgCore
420