1/*
2 * Copyright (C) 2003-2007 Justin Karneges <justin@affinix.com>
3 * Copyright (C) 2004,2005 Brad Hards <bradh@frogmouth.net>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library 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 GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#include "qca_securemessage.h"
23
24#include "qca_safeobj.h"
25#include "qca_safetimer.h"
26#include "qcaprovider.h"
27
28namespace QCA {
29
30Provider::Context *getContext(const QString &type, const QString &provider);
31
32//----------------------------------------------------------------------------
33// SecureMessageKey
34//----------------------------------------------------------------------------
35class SecureMessageKey::Private : public QSharedData
36{
37public:
38 SecureMessageKey::Type type;
39 PGPKey pgp_pub, pgp_sec;
40 CertificateChain cert_pub;
41 PrivateKey cert_sec;
42
43 Private()
44 {
45 type = SecureMessageKey::None;
46 }
47
48 // set the proper type, and reset the opposite data structures if needed
49 void ensureType(SecureMessageKey::Type t)
50 {
51 // if we were non-null and changed, we may need to reset some things
52 if (type != SecureMessageKey::None && t != type) {
53 if (type == SecureMessageKey::X509) {
54 cert_pub = CertificateChain();
55 cert_sec = PrivateKey();
56 } else if (type == SecureMessageKey::PGP) {
57 pgp_pub = PGPKey();
58 pgp_sec = PGPKey();
59 }
60 }
61 type = t;
62 }
63};
64
65SecureMessageKey::SecureMessageKey()
66 : d(new Private)
67{
68}
69
70SecureMessageKey::SecureMessageKey(const SecureMessageKey &from)
71 : d(from.d)
72{
73}
74
75SecureMessageKey::~SecureMessageKey()
76{
77}
78
79SecureMessageKey &SecureMessageKey::operator=(const SecureMessageKey &from)
80{
81 d = from.d;
82 return *this;
83}
84
85bool SecureMessageKey::isNull() const
86{
87 return (d->type == None);
88}
89
90SecureMessageKey::Type SecureMessageKey::type() const
91{
92 return d->type;
93}
94
95PGPKey SecureMessageKey::pgpPublicKey() const
96{
97 return d->pgp_pub;
98}
99
100PGPKey SecureMessageKey::pgpSecretKey() const
101{
102 return d->pgp_sec;
103}
104
105void SecureMessageKey::setPGPPublicKey(const PGPKey &pub)
106{
107 d->ensureType(t: SecureMessageKey::PGP);
108 d->pgp_pub = pub;
109}
110
111void SecureMessageKey::setPGPSecretKey(const PGPKey &sec)
112{
113 d->ensureType(t: SecureMessageKey::PGP);
114 Q_ASSERT(sec.isSecret());
115 d->pgp_sec = sec;
116}
117
118CertificateChain SecureMessageKey::x509CertificateChain() const
119{
120 return d->cert_pub;
121}
122
123PrivateKey SecureMessageKey::x509PrivateKey() const
124{
125 return d->cert_sec;
126}
127
128void SecureMessageKey::setX509CertificateChain(const CertificateChain &c)
129{
130 d->ensureType(t: SecureMessageKey::X509);
131 d->cert_pub = c;
132}
133
134void SecureMessageKey::setX509PrivateKey(const PrivateKey &k)
135{
136 d->ensureType(t: SecureMessageKey::X509);
137 d->cert_sec = k;
138}
139
140void SecureMessageKey::setX509KeyBundle(const KeyBundle &kb)
141{
142 setX509CertificateChain(kb.certificateChain());
143 setX509PrivateKey(kb.privateKey());
144}
145
146bool SecureMessageKey::havePrivate() const
147{
148 if (d->type == SecureMessageKey::PGP && !d->pgp_sec.isNull())
149 return true;
150 else if (d->type == SecureMessageKey::X509 && !d->cert_sec.isNull())
151 return true;
152 return false;
153}
154
155QString SecureMessageKey::name() const
156{
157 if (d->type == SecureMessageKey::PGP && !d->pgp_pub.isNull())
158 return d->pgp_pub.primaryUserId();
159 else if (d->type == SecureMessageKey::X509 && !d->cert_pub.isEmpty())
160 return d->cert_pub.primary().commonName();
161 else
162 return QString();
163}
164
165//----------------------------------------------------------------------------
166// SecureMessageSignature
167//----------------------------------------------------------------------------
168class SecureMessageSignature::Private : public QSharedData
169{
170public:
171 SecureMessageSignature::IdentityResult r;
172 Validity v;
173 SecureMessageKey key;
174 QDateTime ts;
175
176 Private()
177 {
178 r = SecureMessageSignature::NoKey;
179 v = ErrorValidityUnknown;
180 }
181};
182
183SecureMessageSignature::SecureMessageSignature()
184 : d(new Private)
185{
186}
187
188SecureMessageSignature::SecureMessageSignature(IdentityResult r,
189 Validity v,
190 const SecureMessageKey &key,
191 const QDateTime &ts)
192 : d(new Private)
193{
194 d->r = r;
195 d->v = v;
196 d->key = key;
197 d->ts = ts;
198}
199
200SecureMessageSignature::SecureMessageSignature(const SecureMessageSignature &from)
201 : d(from.d)
202{
203}
204
205SecureMessageSignature::~SecureMessageSignature()
206{
207}
208
209SecureMessageSignature &SecureMessageSignature::operator=(const SecureMessageSignature &from)
210{
211 d = from.d;
212 return *this;
213}
214
215SecureMessageSignature::IdentityResult SecureMessageSignature::identityResult() const
216{
217 return d->r;
218}
219
220Validity SecureMessageSignature::keyValidity() const
221{
222 return d->v;
223}
224
225SecureMessageKey SecureMessageSignature::key() const
226{
227 return d->key;
228}
229
230QDateTime SecureMessageSignature::timestamp() const
231{
232 return d->ts;
233}
234
235//----------------------------------------------------------------------------
236// SecureMessage
237//----------------------------------------------------------------------------
238enum ResetMode
239{
240 ResetSession = 0,
241 ResetSessionAndData = 1,
242 ResetAll = 2
243};
244
245class SecureMessage::Private : public QObject
246{
247 Q_OBJECT
248public:
249 SecureMessage *q;
250 MessageContext *c;
251 SecureMessageSystem *system;
252
253 bool bundleSigner, smime;
254 SecureMessage::Format format;
255 SecureMessageKeyList to;
256 SecureMessageKeyList from;
257
258 QByteArray in;
259 bool success;
260 SecureMessage::Error errorCode;
261 QByteArray detachedSig;
262 QString hashName;
263 SecureMessageSignatureList signers;
264 QString dtext;
265
266 QList<int> bytesWrittenArgs;
267 SafeTimer readyReadTrigger, bytesWrittenTrigger, finishedTrigger;
268
269 Private(SecureMessage *_q)
270 : readyReadTrigger(this)
271 , bytesWrittenTrigger(this)
272 , finishedTrigger(this)
273 {
274 q = _q;
275 c = nullptr;
276 system = nullptr;
277
278 readyReadTrigger.setSingleShot(true);
279 bytesWrittenTrigger.setSingleShot(true);
280 finishedTrigger.setSingleShot(true);
281 connect(sender: &readyReadTrigger, signal: &SafeTimer::timeout, context: this, slot: &Private::t_readyRead);
282 connect(sender: &bytesWrittenTrigger, signal: &SafeTimer::timeout, context: this, slot: &Private::t_bytesWritten);
283 connect(sender: &finishedTrigger, signal: &SafeTimer::timeout, context: this, slot: &Private::t_finished);
284
285 reset(mode: ResetAll);
286 }
287
288 void init()
289 {
290 connect(sender: c, signal: &MessageContext::updated, context: this, slot: &Private::updated);
291 }
292
293 void reset(ResetMode mode)
294 {
295 if (c)
296 c->reset();
297
298 bytesWrittenArgs.clear();
299 readyReadTrigger.stop();
300 bytesWrittenTrigger.stop();
301 finishedTrigger.stop();
302
303 if (mode >= ResetSessionAndData) {
304 in.clear();
305 success = false;
306 errorCode = SecureMessage::ErrorUnknown;
307 detachedSig.clear();
308 hashName = QString();
309 signers.clear();
310 }
311
312 if (mode >= ResetAll) {
313 bundleSigner = true;
314 format = SecureMessage::Binary;
315 to.clear();
316 from.clear();
317 }
318 }
319
320public Q_SLOTS:
321 void updated()
322 {
323 bool sig_read = false;
324 bool sig_written = false;
325 bool sig_done = false;
326 int written = 0;
327 {
328 const QByteArray a = c->read();
329 if (!a.isEmpty()) {
330 sig_read = true;
331 in.append(a);
332 }
333
334 const int x = c->written();
335 if (x > 0) {
336 sig_written = true;
337 written = x;
338 }
339 }
340
341 if (c->finished()) {
342 sig_done = true;
343
344 success = c->success();
345 errorCode = c->errorCode();
346 dtext = c->diagnosticText();
347 if (success) {
348 detachedSig = c->signature();
349 hashName = c->hashName();
350 signers = c->signers();
351 }
352 reset(mode: ResetSession);
353 }
354
355 if (sig_read)
356 readyReadTrigger.start();
357 if (sig_written) {
358 bytesWrittenArgs += written;
359 bytesWrittenTrigger.start();
360 }
361 if (sig_done)
362 finishedTrigger.start();
363 }
364
365 void t_readyRead()
366 {
367 emit q->readyRead();
368 }
369
370 void t_bytesWritten()
371 {
372 emit q->bytesWritten(bytes: bytesWrittenArgs.takeFirst());
373 }
374
375 void t_finished()
376 {
377 emit q->finished();
378 }
379};
380
381SecureMessage::SecureMessage(SecureMessageSystem *system)
382{
383 d = new Private(this);
384 d->system = system;
385 d->c = static_cast<SMSContext *>(d->system->context())->createMessage();
386 change(c: d->c);
387 d->init();
388}
389
390SecureMessage::~SecureMessage()
391{
392 delete d;
393}
394
395SecureMessage::Type SecureMessage::type() const
396{
397 return d->c->type();
398}
399
400bool SecureMessage::canSignMultiple() const
401{
402 return d->c->canSignMultiple();
403}
404
405bool SecureMessage::canClearsign() const
406{
407 return (type() == OpenPGP);
408}
409
410bool SecureMessage::canSignAndEncrypt() const
411{
412 return (type() == OpenPGP);
413}
414
415void SecureMessage::reset()
416{
417 d->reset(mode: ResetAll);
418}
419
420bool SecureMessage::bundleSignerEnabled() const
421{
422 return d->bundleSigner;
423}
424
425bool SecureMessage::smimeAttributesEnabled() const
426{
427 return d->smime;
428}
429
430SecureMessage::Format SecureMessage::format() const
431{
432 return d->format;
433}
434
435SecureMessageKeyList SecureMessage::recipientKeys() const
436{
437 return d->to;
438}
439
440SecureMessageKeyList SecureMessage::signerKeys() const
441{
442 return d->from;
443}
444
445void SecureMessage::setBundleSignerEnabled(bool b)
446{
447 d->bundleSigner = b;
448}
449
450void SecureMessage::setSMIMEAttributesEnabled(bool b)
451{
452 d->smime = b;
453}
454
455void SecureMessage::setFormat(Format f)
456{
457 d->format = f;
458}
459
460void SecureMessage::setRecipient(const SecureMessageKey &key)
461{
462 d->to = SecureMessageKeyList() << key;
463}
464
465void SecureMessage::setRecipients(const SecureMessageKeyList &keys)
466{
467 d->to = keys;
468}
469
470void SecureMessage::setSigner(const SecureMessageKey &key)
471{
472 d->from = SecureMessageKeyList() << key;
473}
474
475void SecureMessage::setSigners(const SecureMessageKeyList &keys)
476{
477 d->from = keys;
478}
479
480void SecureMessage::startEncrypt()
481{
482 d->reset(mode: ResetSessionAndData);
483 d->c->setupEncrypt(d->to);
484 d->c->start(f: d->format, op: MessageContext::Encrypt);
485}
486
487void SecureMessage::startDecrypt()
488{
489 d->reset(mode: ResetSessionAndData);
490 d->c->start(f: d->format, op: MessageContext::Decrypt);
491}
492
493void SecureMessage::startSign(SignMode m)
494{
495 d->reset(mode: ResetSessionAndData);
496 d->c->setupSign(keys: d->from, m, bundleSigner: d->bundleSigner, smime: d->smime);
497 d->c->start(f: d->format, op: MessageContext::Sign);
498}
499
500void SecureMessage::startVerify(const QByteArray &sig)
501{
502 d->reset(mode: ResetSessionAndData);
503 if (!sig.isEmpty())
504 d->c->setupVerify(sig);
505 d->c->start(f: d->format, op: MessageContext::Verify);
506}
507
508void SecureMessage::startSignAndEncrypt()
509{
510 d->reset(mode: ResetSessionAndData);
511 d->c->setupEncrypt(d->to);
512 d->c->setupSign(keys: d->from, m: Message, bundleSigner: d->bundleSigner, smime: d->smime);
513 d->c->start(f: d->format, op: MessageContext::SignAndEncrypt);
514}
515
516void SecureMessage::update(const QByteArray &in)
517{
518 d->c->update(in);
519}
520
521QByteArray SecureMessage::read()
522{
523 const QByteArray a = d->in;
524 d->in.clear();
525 return a;
526}
527
528int SecureMessage::bytesAvailable() const
529{
530 return d->in.size();
531}
532
533void SecureMessage::end()
534{
535 d->c->end();
536}
537
538bool SecureMessage::waitForFinished(int msecs)
539{
540 d->c->waitForFinished(msecs);
541 d->updated();
542 return d->success;
543}
544
545bool SecureMessage::success() const
546{
547 return d->success;
548}
549
550SecureMessage::Error SecureMessage::errorCode() const
551{
552 return d->errorCode;
553}
554
555QByteArray SecureMessage::signature() const
556{
557 return d->detachedSig;
558}
559
560QString SecureMessage::hashName() const
561{
562 return d->hashName;
563}
564
565bool SecureMessage::wasSigned() const
566{
567 return !d->signers.isEmpty();
568}
569
570bool SecureMessage::verifySuccess() const
571{
572 // if we're not done or there were no signers, then return false
573 if (!d->success || d->signers.isEmpty())
574 return false;
575
576 // make sure all signers have a valid signature
577 for (int n = 0; n < d->signers.count(); ++n) {
578 if (d->signers[n].identityResult() != SecureMessageSignature::Valid)
579 return false;
580 }
581 return true;
582}
583
584SecureMessageSignature SecureMessage::signer() const
585{
586 if (d->signers.isEmpty())
587 return SecureMessageSignature();
588
589 return d->signers.first();
590}
591
592SecureMessageSignatureList SecureMessage::signers() const
593{
594 return d->signers;
595}
596
597QString SecureMessage::diagnosticText() const
598{
599 return d->dtext;
600}
601
602//----------------------------------------------------------------------------
603// SecureMessageSystem
604//----------------------------------------------------------------------------
605SecureMessageSystem::SecureMessageSystem(QObject *parent, const QString &type, const QString &provider)
606 : QObject(parent)
607 , Algorithm(type, provider)
608{
609}
610
611SecureMessageSystem::~SecureMessageSystem()
612{
613}
614
615//----------------------------------------------------------------------------
616// OpenPGP
617//----------------------------------------------------------------------------
618OpenPGP::OpenPGP(QObject *parent, const QString &provider)
619 : SecureMessageSystem(parent, QStringLiteral("openpgp"), provider)
620{
621}
622
623OpenPGP::~OpenPGP()
624{
625}
626
627//----------------------------------------------------------------------------
628// CMS
629//----------------------------------------------------------------------------
630class CMS::Private
631{
632public:
633 CertificateCollection trusted, untrusted;
634 SecureMessageKeyList privateKeys;
635};
636
637CMS::CMS(QObject *parent, const QString &provider)
638 : SecureMessageSystem(parent, QStringLiteral("cms"), provider)
639{
640 d = new Private;
641}
642
643CMS::~CMS()
644{
645 delete d;
646}
647
648CertificateCollection CMS::trustedCertificates() const
649{
650 return d->trusted;
651}
652
653CertificateCollection CMS::untrustedCertificates() const
654{
655 return d->untrusted;
656}
657
658SecureMessageKeyList CMS::privateKeys() const
659{
660 return d->privateKeys;
661}
662
663void CMS::setTrustedCertificates(const CertificateCollection &trusted)
664{
665 d->trusted = trusted;
666 static_cast<SMSContext *>(context())->setTrustedCertificates(trusted);
667}
668
669void CMS::setUntrustedCertificates(const CertificateCollection &untrusted)
670{
671 d->untrusted = untrusted;
672 static_cast<SMSContext *>(context())->setUntrustedCertificates(untrusted);
673}
674
675void CMS::setPrivateKeys(const SecureMessageKeyList &keys)
676{
677 d->privateKeys = keys;
678 static_cast<SMSContext *>(context())->setPrivateKeys(keys);
679}
680
681}
682
683#include "qca_securemessage.moc"
684

source code of qca/src/qca_securemessage.cpp